[PATCH v3] [media] v4l2: Add support for go2001 PCI codec driver
This patch adds support for the go2001 PCI codec driver. This hardware is present on ChromeOS based devices like the Acer ChromeBox and Acer/LG ChromeBase 24 devices. This chipset comes on a mini PCI-E card with Google as PCI vendor ID (0x1ae0). This driver comes from the ChromeOS v3.18 kernel tree and has been modified to support vb2_buffer restructuring introduced in Linux v4.4. The go2001 firmware files can be found in the build tree of the Google Chromium OS open source project. This driver is originally developed by: Pawel Osciak <posc...@chromium.org> Ville-Mikko Rautio <v...@chromium.org> henryhsu <henry...@chromium.org> Wu-Cheng Li <wuchen...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/pci/Kconfig|2 + drivers/media/pci/Makefile |1 + drivers/media/pci/go2001/Kconfig | 11 + drivers/media/pci/go2001/Makefile|2 + drivers/media/pci/go2001/go2001.h| 331 drivers/media/pci/go2001/go2001_driver.c | 2525 ++ drivers/media/pci/go2001/go2001_hw.c | 1362 drivers/media/pci/go2001/go2001_hw.h | 55 + drivers/media/pci/go2001/go2001_proto.h | 359 + 9 files changed, 4648 insertions(+) create mode 100644 drivers/media/pci/go2001/Kconfig create mode 100644 drivers/media/pci/go2001/Makefile create mode 100644 drivers/media/pci/go2001/go2001.h create mode 100644 drivers/media/pci/go2001/go2001_driver.c create mode 100644 drivers/media/pci/go2001/go2001_hw.c create mode 100644 drivers/media/pci/go2001/go2001_hw.h create mode 100644 drivers/media/pci/go2001/go2001_proto.h diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig index da28e68..837681e 100644 --- a/drivers/media/pci/Kconfig +++ b/drivers/media/pci/Kconfig @@ -54,5 +54,7 @@ source "drivers/media/pci/smipcie/Kconfig" source "drivers/media/pci/netup_unidvb/Kconfig" endif +source "drivers/media/pci/go2001/Kconfig" + endif #MEDIA_PCI_SUPPORT endif #PCI diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile index a7e8af0..58639b7 100644 --- a/drivers/media/pci/Makefile +++ b/drivers/media/pci/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_STA2X11_VIP) += sta2x11/ obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ obj-$(CONFIG_VIDEO_COBALT) += cobalt/ obj-$(CONFIG_VIDEO_TW5864) += tw5864/ +obj-$(CONFIG_VIDEO_GO2001) += go2001/ diff --git a/drivers/media/pci/go2001/Kconfig b/drivers/media/pci/go2001/Kconfig new file mode 100644 index 000..c7b5149 --- /dev/null +++ b/drivers/media/pci/go2001/Kconfig @@ -0,0 +1,11 @@ +config VIDEO_GO2001 + tristate "GO2001 codec driver" + depends on VIDEO_V4L2 && PCI + select VIDEOBUF2_DMA_SG + ---help--- + This driver supports the GO2001 PCI hardware codec. This codec + is present on ChromeOS based devices like the Acer ChromeBox + and ChromeBase 24 and LG ChromeBase as well. + + To compile this driver as a module, choose M here: the + module will be called go2001. diff --git a/drivers/media/pci/go2001/Makefile b/drivers/media/pci/go2001/Makefile new file mode 100644 index 000..20bad18 --- /dev/null +++ b/drivers/media/pci/go2001/Makefile @@ -0,0 +1,2 @@ +go2001-objs:= go2001_driver.o go2001_hw.o +obj-$(CONFIG_VIDEO_GO2001) += go2001.o diff --git a/drivers/media/pci/go2001/go2001.h b/drivers/media/pci/go2001/go2001.h new file mode 100644 index 000..0e5ccfd --- /dev/null +++ b/drivers/media/pci/go2001/go2001.h @@ -0,0 +1,331 @@ +/* + * go2001 - GO2001 codec driver. + * + * Author : Pawel Osciak <posc...@chromium.org> + * + * Copyright (C) 2017 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _MEDIA_PCI_GO2001_GO2001_H_ +#define _MEDIA_PCI_GO2001_GO2001_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "go2001_proto.h" + +struct go2001_msg { + struct list_head list_entry; + struct go2001_msg_payload payload; +}; + +static inline struct go2001_msg_hdr *msg_to_hdr(struct go2001_msg *msg) +{ + return >payload.hdr; +} + +static inline void *msg_to_param(struct go2001_msg *msg) +{ + return ms
[PATCH v3] go2001 hardware codec support
Multiplanar Streaming Extended Pix Format Compliance test for device /dev/video1 (not using libv4l2): Required ioctls: test VIDIOC_QUERYCAP: OK Allow for multiple opens: test second video open: OK test VIDIOC_QUERYCAP: OK test VIDIOC_G/S_PRIORITY: OK test for unlimited opens: OK Debug ioctls: test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported) test VIDIOC_LOG_STATUS: OK (Not Supported) Input ioctls: test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported) test VIDIOC_G/S_FREQUENCY: OK (Not Supported) test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported) test VIDIOC_ENUMAUDIO: OK (Not Supported) test VIDIOC_G/S/ENUMINPUT: OK (Not Supported) test VIDIOC_G/S_AUDIO: OK (Not Supported) Inputs: 0 Audio Inputs: 0 Tuners: 0 Output ioctls: test VIDIOC_G/S_MODULATOR: OK (Not Supported) test VIDIOC_G/S_FREQUENCY: OK (Not Supported) test VIDIOC_ENUMAUDOUT: OK (Not Supported) test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported) test VIDIOC_G/S_AUDOUT: OK (Not Supported) Outputs: 0 Audio Outputs: 0 Modulators: 0 Input/Output configuration ioctls: test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported) test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported) test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported) test VIDIOC_G/S_EDID: OK (Not Supported) Control ioctls: test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK test VIDIOC_QUERYCTRL: OK test VIDIOC_G/S_CTRL: OK test VIDIOC_G/S/TRY_EXT_CTRLS: OK test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK test VIDIOC_G/S_JPEGCOMP: OK (Not Supported) Standard Controls: 4 Private Controls: 0 Format ioctls: test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK fail: v4l2-test-formats.cpp(1213): got error 22 when setting parms for buftype 10 test VIDIOC_G/S_PARM: FAIL test VIDIOC_G_FBUF: OK (Not Supported) fail: v4l2-test-formats.cpp(446): !pix_mp.width || !pix_mp.height test VIDIOC_G_FMT: FAIL test VIDIOC_TRY_FMT: OK (Not Supported) test VIDIOC_S_FMT: OK (Not Supported) test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported) test Cropping: OK (Not Supported) test Composing: OK (Not Supported) fail: v4l2-test-formats.cpp(1678): doioctl(node, VIDIOC_G_FMT, ) test Scaling: FAIL Codec ioctls: test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported) test VIDIOC_G_ENC_INDEX: OK (Not Supported) test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported) Buffer ioctls: test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK fail: v4l2-test-buffers.cpp(574): VIDIOC_EXPBUF is supported, but the V4L2_MEMORY_MMAP support is missing, probably due to earlier failing format tests. test VIDIOC_EXPBUF: OK (Not Supported) Test input 0: Total: 43, Succeeded: 40, Failed: 3, Warnings: 0 Thierry Escande (1): [media] v4l2: Add support for go2001 PCI codec driver drivers/media/pci/Kconfig|2 + drivers/media/pci/Makefile |1 + drivers/media/pci/go2001/Kconfig | 11 + drivers/media/pci/go2001/Makefile|2 + drivers/media/pci/go2001/go2001.h| 331 drivers/media/pci/go2001/go2001_driver.c | 2525 ++ drivers/media/pci/go2001/go2001_hw.c | 1362 drivers/media/pci/go2001/go2001_hw.h | 55 + drivers/media/pci/go2001/go2001_proto.h | 359 + 9 files changed, 4648 insertions(+) create mode 100644 drivers/media/pci/go2001/Kconfig create mode 100644 drivers/media/pci/go2001/Makefile create mode 100644 drivers/media/pci/go2001/go2001.h create mode 100644 drivers/media/pci/go2001/go2001_driver.c create mode 100644 drivers/media/pci/go2001/go2001_hw.c create mode 100644 drivers/media/pci/go2001/go2001_hw.h create mode 100644 drivers/media/pci/go2001/go2001_proto.h -- 2.7.4
[PATCH v4 3/8] [media] s5p-jpeg: Handle parsing error in s5p_jpeg_parse_hdr()
This patch modifies the s5p_jpeg_parse_hdr() function so it only modifies the passed s5p_jpeg_q_data structure if the jpeg header parsing is successful. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 38 - 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 0d935f5..df3e5ee 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1206,22 +1206,9 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, break; } } - result->w = width; - result->h = height; - result->sos = sos; - result->dht.n = n_dht; - while (n_dht--) { - result->dht.marker[n_dht] = dht[n_dht]; - result->dht.len[n_dht] = dht_len[n_dht]; - } - result->dqt.n = n_dqt; - while (n_dqt--) { - result->dqt.marker[n_dqt] = dqt[n_dqt]; - result->dqt.len[n_dqt] = dqt_len[n_dqt]; - } - result->sof = sof; - result->sof_len = sof_len; - result->size = result->components = components; + + if (notfound || !sos) + return false; switch (subsampling) { case 0x11: @@ -1240,7 +1227,24 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, return false; } - return !notfound && sos; + result->w = width; + result->h = height; + result->sos = sos; + result->dht.n = n_dht; + while (n_dht--) { + result->dht.marker[n_dht] = dht[n_dht]; + result->dht.len[n_dht] = dht_len[n_dht]; + } + result->dqt.n = n_dqt; + while (n_dqt--) { + result->dqt.marker[n_dqt] = dqt[n_dqt]; + result->dqt.len[n_dqt] = dqt_len[n_dqt]; + } + result->sof = sof; + result->sof_len = sof_len; + result->size = result->components = components; + + return true; } static int s5p_jpeg_querycap(struct file *file, void *priv, -- 2.7.4
[PATCH v4 4/8] [media] s5p-jpeg: Don't use temporary structure in s5p_jpeg_buf_queue
If s5p_jpeg_parse_hdr() fails to parse the JPEG header, the passed s5p_jpeg_q_data structure is not modified so there is no need to use a temporary structure and the field-by-field copy can be avoided. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 23 --- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index df3e5ee..1769744 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2500,9 +2500,9 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) if (ctx->mode == S5P_JPEG_DECODE && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - struct s5p_jpeg_q_data tmp, *q_data; + struct s5p_jpeg_q_data *q_data; - ctx->hdr_parsed = s5p_jpeg_parse_hdr(, + ctx->hdr_parsed = s5p_jpeg_parse_hdr(>out_q, (unsigned long)vb2_plane_vaddr(vb, 0), min((unsigned long)ctx->out_q.size, vb2_get_plane_payload(vb, 0)), ctx); @@ -2511,24 +2511,9 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) return; } - q_data = >out_q; - q_data->w = tmp.w; - q_data->h = tmp.h; - q_data->sos = tmp.sos; - memcpy(q_data->dht.marker, tmp.dht.marker, - sizeof(tmp.dht.marker)); - memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len)); - q_data->dht.n = tmp.dht.n; - memcpy(q_data->dqt.marker, tmp.dqt.marker, - sizeof(tmp.dqt.marker)); - memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len)); - q_data->dqt.n = tmp.dqt.n; - q_data->sof = tmp.sof; - q_data->sof_len = tmp.sof_len; - q_data = >cap_q; - q_data->w = tmp.w; - q_data->h = tmp.h; + q_data->w = ctx->out_q.w; + q_data->h = ctx->out_q.h; /* * This call to jpeg_bound_align_image() takes care of width and -- 2.7.4
[PATCH v4 6/8] [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format
From: Tony K Nadackal <tony...@samsung.com> This patch adds support for decoding 4:1:1 chroma subsampling in the jpeg header parsing function. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 0783809..cca0fb8 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1099,6 +1099,8 @@ static void skip(struct s5p_jpeg_buffer *buf, long len) static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx, unsigned int subsampling) { + unsigned int version; + switch (subsampling) { case 0x11: ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444; @@ -1112,6 +1114,19 @@ static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx, case 0x33: ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; break; + case 0x41: + /* +* 4:1:1 subsampling only supported by 3250, 5420, and 5433 +* variants +*/ + version = ctx->jpeg->variant->version; + if (version != SJPEG_EXYNOS3250 && + version != SJPEG_EXYNOS5420 && + version != SJPEG_EXYNOS5433) + return false; + + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411; + break; default: return false; } -- 2.7.4
[PATCH v4 1/8] [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf
From: Tony K Nadackal <tony...@samsung.com> When queuing an OUTPUT buffer for decoder, s5p_jpeg_parse_hdr() function parses the input jpeg file and takes the width and height parameters from its header. These new width/height values will be used for the calculation of stride. HX_JPEG Hardware needs the width and height values aligned on a 16 bits boundary. This width/height alignment is handled in the s5p_jpeg_s_fmt_vid_cap() function during the S_FMT ioctl call. But if user space calls the QBUF of OUTPUT buffer after the S_FMT of CAPTURE buffer, these aligned values will be replaced by the values in jpeg header. If the width/height values of jpeg are not aligned, the decoder output will be corrupted. So in this patch we call jpeg_bound_align_image() to align the width/height values of Capture buffer in s5p_jpeg_buf_queue(). Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 52dc794..623508d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2523,6 +2523,25 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) q_data = >cap_q; q_data->w = tmp.w; q_data->h = tmp.h; + + /* +* This call to jpeg_bound_align_image() takes care of width and +* height values alignment when user space calls the QBUF of +* OUTPUT buffer after the S_FMT of CAPTURE buffer. +* Please note that on Exynos4x12 SoCs, resigning from executing +* S_FMT on capture buffer for each JPEG image can result in a +* hardware hangup if subsampling is lower than the one of input +* JPEG. +*/ + jpeg_bound_align_image(ctx, + _data->w, + S5P_JPEG_MIN_WIDTH, S5P_JPEG_MAX_WIDTH, + q_data->fmt->h_align, + _data->h, + S5P_JPEG_MIN_HEIGHT, S5P_JPEG_MAX_HEIGHT, + q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; } v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); -- 2.7.4
[PATCH v4 5/8] [media] s5p-jpeg: Split s5p_jpeg_parse_hdr()
This patch moves the subsampling value decoding read from the jpeg header into its own function. This new function is called s5p_jpeg_subsampling_decode() and returns true if it successfully decodes the subsampling value, false otherwise. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 42 - 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 1769744..0783809 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1096,6 +1096,29 @@ static void skip(struct s5p_jpeg_buffer *buf, long len) get_byte(buf); } +static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx, + unsigned int subsampling) +{ + switch (subsampling) { + case 0x11: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444; + break; + case 0x21: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422; + break; + case 0x22: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420; + break; + case 0x33: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; + break; + default: + return false; + } + + return true; +} + static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, unsigned long buffer, unsigned long size, struct s5p_jpeg_ctx *ctx) @@ -1207,26 +1230,9 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, } } - if (notfound || !sos) + if (notfound || !sos || !s5p_jpeg_subsampling_decode(ctx, subsampling)) return false; - switch (subsampling) { - case 0x11: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444; - break; - case 0x21: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422; - break; - case 0x22: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420; - break; - case 0x33: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; - break; - default: - return false; - } - result->w = width; result->h = height; result->sos = sos; -- 2.7.4
[PATCH v4 8/8] [media] s5p-jpeg: Add stream error handling for Exynos5420
From: henryhsu <henry...@chromium.org> On Exynos5420, the STREAM_STAT bit raised on the JPGINTST register means there is a syntax error or an unrecoverable error on compressed file when ERR_INT_EN is set to 1. Fix this case and report BUF_STATE_ERROR to videobuf2. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 5ad3d43..c35d169 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2812,6 +2812,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) unsigned long payload_size = 0; enum vb2_buffer_state state = VB2_BUF_STATE_DONE; bool interrupt_timeout = false; + bool stream_error = false; u32 irq_status; spin_lock(>slock); @@ -2828,6 +2829,12 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) jpeg->irq_status |= irq_status; + if (jpeg->variant->version == SJPEG_EXYNOS5420 && + irq_status & EXYNOS3250_STREAM_STAT) { + stream_error = true; + dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n"); + } + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); if (!curr_ctx) @@ -2844,7 +2851,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) EXYNOS3250_RDMA_DONE | EXYNOS3250_RESULT_STAT)) payload_size = exynos3250_jpeg_compressed_size(jpeg->regs); - else if (interrupt_timeout) + else if (interrupt_timeout || stream_error) state = VB2_BUF_STATE_ERROR; else goto exit_unlock; -- 2.7.4
[PATCH v4 7/8] [media] s5p-jpeg: Add support for resolution change event
From: henryhsu <henry...@chromium.org> This patch adds support for resolution change event to notify clients so they can prepare correct output buffer. When resolution change happened, G_FMT for CAPTURE should return old resolution and format before CAPTURE queues streamoff. This event is used in the Chromium browser project by the V4L2 JPEG Decode Accelerator (V4L2JDA) to allocate output buffer. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 106 +--- drivers/media/platform/s5p-jpeg/jpeg-core.h | 7 ++ 2 files changed, 89 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index cca0fb8..5ad3d43 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1633,8 +1634,6 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE; q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type); - q_data->w = pix->width; - q_data->h = pix->height; if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) { /* * During encoding Exynos4x12 SoCs access wider memory area @@ -1642,6 +1641,8 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu * page fault calculate proper buffer size in such a case. */ + q_data->w = pix->width; + q_data->h = pix->height; if (ct->jpeg->variant->hw_ex4_compat && f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE) q_data->size = exynos4_jpeg_get_output_buffer_size(ct, @@ -1717,6 +1718,15 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); } +static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + if (sub->type == V4L2_EVENT_SOURCE_CHANGE) + return v4l2_src_change_event_subscribe(fh, sub); + + return -EINVAL; +} + static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, struct v4l2_rect *r) { @@ -2042,6 +2052,9 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { .vidioc_g_selection = s5p_jpeg_g_selection, .vidioc_s_selection = s5p_jpeg_s_selection, + + .vidioc_subscribe_event = s5p_jpeg_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* @@ -2434,8 +2447,17 @@ static int s5p_jpeg_job_ready(void *priv) { struct s5p_jpeg_ctx *ctx = priv; - if (ctx->mode == S5P_JPEG_DECODE) + if (ctx->mode == S5P_JPEG_DECODE) { + /* +* We have only one input buffer and one output buffer. If there +* is a resolution change event, no need to continue decoding. +*/ + if (ctx->state == JPEGCTX_RESOLUTION_CHANGE) + return 0; + return ctx->hdr_parsed; + } + return 1; } @@ -2514,6 +2536,30 @@ static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb) return 0; } +static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg_q_data *q_data = >cap_q; + + q_data->w = ctx->out_q.w; + q_data->h = ctx->out_q.h; + + /* +* This call to jpeg_bound_align_image() takes care of width and +* height values alignment when user space calls the QBUF of +* OUTPUT buffer after the S_FMT of CAPTURE buffer. +* Please note that on Exynos4x12 SoCs, resigning from executing +* S_FMT on capture buffer for each JPEG image can result in a +* hardware hangup if subsampling is lower than the one of input +* JPEG. +*/ + jpeg_bound_align_image(ctx, _data->w, S5P_JPEG_MIN_WIDTH, + S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align, + _data->h, S5P_JPEG_MIN_HEIGHT, + S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; +} + static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) { struct v
[PATCH v4 2/8] [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling
From: Tony K Nadackal <tony...@samsung.com> Corrects the WARN_ON statement for subsampling based on the JPEG Hardware version. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Acked-by: Andrzej Pietrasiewicz <andrze...@samsung.com> Acked-by: Jacek Anaszewski <jacek.anaszew...@gmail.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 623508d..0d935f5 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -614,24 +614,26 @@ static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) { - WARN_ON(ctx->subsampling > 3); - switch (ctx->jpeg->variant->version) { case SJPEG_S5P: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; return ctx->subsampling; case SJPEG_EXYNOS3250: case SJPEG_EXYNOS5420: + WARN_ON(ctx->subsampling > 6); if (ctx->subsampling > 3) return V4L2_JPEG_CHROMA_SUBSAMPLING_411; return exynos3250_decoded_subsampling[ctx->subsampling]; case SJPEG_EXYNOS4: case SJPEG_EXYNOS5433: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_420; return exynos4x12_decoded_subsampling[ctx->subsampling]; default: + WARN_ON(ctx->subsampling > 3); return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; } } -- 2.7.4
[PATCH v4 0/8] [media] s5p-jpeg: Various fixes and improvements
Hi, This series contains various fixes and improvements for the Samsung s5p-jpeg driver. Most of these patches come from the Chromium v3.8 kernel tree. In this v4: - Correct a typo in patch #04 commit message (Thanks Jacek) - Add Acked-by from Andrzej and Jacek for the whole series v3: - Remove codec reset patch (Not needed based on documentation and no use case described in original patch commit message). - Check for Exynos5420 variant in stream error handling patch. - Add use case for resolution change event support in commit message. - Move subsampling value decoding in a separate function. - Check Exynos variant for 4:1:1 subsampling support. v2: - Remove IOMMU support patch (mapping now created automatically for single JPEG CODEC device). - Remove "Change sclk_jpeg to 166MHz" patch (can be set through DT properties). - Remove support for multi-planar APIs (Not needed). - Add comment regarding call to jpeg_bound_align_image() after qbuf. - Remove unrelated code from resolution change event support patch. Thierry Escande (3): [media] s5p-jpeg: Handle parsing error in s5p_jpeg_parse_hdr() [media] s5p-jpeg: Don't use temporary structure in s5p_jpeg_buf_queue [media] s5p-jpeg: Split s5p_jpeg_parse_hdr() Tony K Nadackal (3): [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format henryhsu (2): [media] s5p-jpeg: Add support for resolution change event [media] s5p-jpeg: Add stream error handling for Exynos5420 drivers/media/platform/s5p-jpeg/jpeg-core.c | 186 +--- drivers/media/platform/s5p-jpeg/jpeg-core.h | 7 ++ 2 files changed, 148 insertions(+), 45 deletions(-) -- 2.7.4
[PATCH v3 0/8] [media] s5p-jpeg: Various fixes and improvements
Hi, This series contains various fixes and improvements for the Samsung s5p-jpeg driver. Most of these patches come from the Chromium v3.8 kernel tree. In this v3: - Remove codec reset patch (Not needed based on documentation and no use case described in original patch commit message). - Check for Exynos5420 variant in stream error handling patch. - Add use case for resolution change event support in commit message. - Move subsampling value decoding in a separate function. - Check Exynos variant for 4:1:1 subsampling support. v2: - Remove IOMMU support patch (mapping now created automatically for single JPEG CODEC device). - Remove "Change sclk_jpeg to 166MHz" patch (can be set through DT properties). - Remove support for multi-planar APIs (Not needed). - Add comment regarding call to jpeg_bound_align_image() after qbuf. - Remove unrelated code from resolution change event support patch. Thierry Escande (3): [media] s5p-jpeg: Handle parsing error in s5p_jpeg_parse_hdr() [media] s5p-jpeg: Don't use temporary structure in s5p_jpeg_buf_queue [media] s5p-jpeg: Split s5p_jpeg_parse_hdr() Tony K Nadackal (3): [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format henryhsu (2): [media] s5p-jpeg: Add support for resolution change event [media] s5p-jpeg: Add stream error handling for Exynos5420 drivers/media/platform/s5p-jpeg/jpeg-core.c | 186 +--- drivers/media/platform/s5p-jpeg/jpeg-core.h | 7 ++ 2 files changed, 148 insertions(+), 45 deletions(-) -- 2.7.4
[PATCH v3 4/8] [media] s5p-jpeg: Don't use temporary structure in s5p_jpeg_buf_queue
If s5p_jpeg_parse_hdr() fails to parse the JPEG header, the passed s5p_jpeg_q_data structure is not modify so there is no need to use a temporary structure and the field-by-field copy can be avoided. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 23 --- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index df3e5ee..1769744 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2500,9 +2500,9 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) if (ctx->mode == S5P_JPEG_DECODE && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - struct s5p_jpeg_q_data tmp, *q_data; + struct s5p_jpeg_q_data *q_data; - ctx->hdr_parsed = s5p_jpeg_parse_hdr(, + ctx->hdr_parsed = s5p_jpeg_parse_hdr(>out_q, (unsigned long)vb2_plane_vaddr(vb, 0), min((unsigned long)ctx->out_q.size, vb2_get_plane_payload(vb, 0)), ctx); @@ -2511,24 +2511,9 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) return; } - q_data = >out_q; - q_data->w = tmp.w; - q_data->h = tmp.h; - q_data->sos = tmp.sos; - memcpy(q_data->dht.marker, tmp.dht.marker, - sizeof(tmp.dht.marker)); - memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len)); - q_data->dht.n = tmp.dht.n; - memcpy(q_data->dqt.marker, tmp.dqt.marker, - sizeof(tmp.dqt.marker)); - memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len)); - q_data->dqt.n = tmp.dqt.n; - q_data->sof = tmp.sof; - q_data->sof_len = tmp.sof_len; - q_data = >cap_q; - q_data->w = tmp.w; - q_data->h = tmp.h; + q_data->w = ctx->out_q.w; + q_data->h = ctx->out_q.h; /* * This call to jpeg_bound_align_image() takes care of width and -- 2.7.4
[PATCH v3 7/8] [media] s5p-jpeg: Add support for resolution change event
From: henryhsu <henry...@chromium.org> This patch adds support for resolution change event to notify clients so they can prepare correct output buffer. When resolution change happened, G_FMT for CAPTURE should return old resolution and format before CAPTURE queues streamoff. This event is used in the Chromium browser project by the V4L2 JPEG Decode Accelerator (V4L2JDA) to allocate output buffer. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 106 +--- drivers/media/platform/s5p-jpeg/jpeg-core.h | 7 ++ 2 files changed, 89 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index cca0fb8..5ad3d43 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1633,8 +1634,6 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE; q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type); - q_data->w = pix->width; - q_data->h = pix->height; if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) { /* * During encoding Exynos4x12 SoCs access wider memory area @@ -1642,6 +1641,8 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu * page fault calculate proper buffer size in such a case. */ + q_data->w = pix->width; + q_data->h = pix->height; if (ct->jpeg->variant->hw_ex4_compat && f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE) q_data->size = exynos4_jpeg_get_output_buffer_size(ct, @@ -1717,6 +1718,15 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); } +static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + if (sub->type == V4L2_EVENT_SOURCE_CHANGE) + return v4l2_src_change_event_subscribe(fh, sub); + + return -EINVAL; +} + static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, struct v4l2_rect *r) { @@ -2042,6 +2052,9 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { .vidioc_g_selection = s5p_jpeg_g_selection, .vidioc_s_selection = s5p_jpeg_s_selection, + + .vidioc_subscribe_event = s5p_jpeg_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* @@ -2434,8 +2447,17 @@ static int s5p_jpeg_job_ready(void *priv) { struct s5p_jpeg_ctx *ctx = priv; - if (ctx->mode == S5P_JPEG_DECODE) + if (ctx->mode == S5P_JPEG_DECODE) { + /* +* We have only one input buffer and one output buffer. If there +* is a resolution change event, no need to continue decoding. +*/ + if (ctx->state == JPEGCTX_RESOLUTION_CHANGE) + return 0; + return ctx->hdr_parsed; + } + return 1; } @@ -2514,6 +2536,30 @@ static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb) return 0; } +static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg_q_data *q_data = >cap_q; + + q_data->w = ctx->out_q.w; + q_data->h = ctx->out_q.h; + + /* +* This call to jpeg_bound_align_image() takes care of width and +* height values alignment when user space calls the QBUF of +* OUTPUT buffer after the S_FMT of CAPTURE buffer. +* Please note that on Exynos4x12 SoCs, resigning from executing +* S_FMT on capture buffer for each JPEG image can result in a +* hardware hangup if subsampling is lower than the one of input +* JPEG. +*/ + jpeg_bound_align_image(ctx, _data->w, S5P_JPEG_MIN_WIDTH, + S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align, + _data->h, S5P_JPEG_MIN_HEIGHT, + S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; +} + static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -2521,7 +2567,18 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
[PATCH v3 6/8] [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format
From: Tony K Nadackal <tony...@samsung.com> This patch adds support for decoding 4:1:1 chroma subsampling in the jpeg header parsing function. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 0783809..cca0fb8 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1099,6 +1099,8 @@ static void skip(struct s5p_jpeg_buffer *buf, long len) static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx, unsigned int subsampling) { + unsigned int version; + switch (subsampling) { case 0x11: ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444; @@ -1112,6 +1114,19 @@ static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx, case 0x33: ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; break; + case 0x41: + /* +* 4:1:1 subsampling only supported by 3250, 5420, and 5433 +* variants +*/ + version = ctx->jpeg->variant->version; + if (version != SJPEG_EXYNOS3250 && + version != SJPEG_EXYNOS5420 && + version != SJPEG_EXYNOS5433) + return false; + + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411; + break; default: return false; } -- 2.7.4
[PATCH v3 3/8] [media] s5p-jpeg: Handle parsing error in s5p_jpeg_parse_hdr()
This patch modifies the s5p_jpeg_parse_hdr() function so it only modifies the passed s5p_jpeg_q_data structure if the jpeg header parsing is successful. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 38 - 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 0d935f5..df3e5ee 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1206,22 +1206,9 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, break; } } - result->w = width; - result->h = height; - result->sos = sos; - result->dht.n = n_dht; - while (n_dht--) { - result->dht.marker[n_dht] = dht[n_dht]; - result->dht.len[n_dht] = dht_len[n_dht]; - } - result->dqt.n = n_dqt; - while (n_dqt--) { - result->dqt.marker[n_dqt] = dqt[n_dqt]; - result->dqt.len[n_dqt] = dqt_len[n_dqt]; - } - result->sof = sof; - result->sof_len = sof_len; - result->size = result->components = components; + + if (notfound || !sos) + return false; switch (subsampling) { case 0x11: @@ -1240,7 +1227,24 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, return false; } - return !notfound && sos; + result->w = width; + result->h = height; + result->sos = sos; + result->dht.n = n_dht; + while (n_dht--) { + result->dht.marker[n_dht] = dht[n_dht]; + result->dht.len[n_dht] = dht_len[n_dht]; + } + result->dqt.n = n_dqt; + while (n_dqt--) { + result->dqt.marker[n_dqt] = dqt[n_dqt]; + result->dqt.len[n_dqt] = dqt_len[n_dqt]; + } + result->sof = sof; + result->sof_len = sof_len; + result->size = result->components = components; + + return true; } static int s5p_jpeg_querycap(struct file *file, void *priv, -- 2.7.4
[PATCH v3 8/8] [media] s5p-jpeg: Add stream error handling for Exynos5420
From: henryhsu <henry...@chromium.org> On Exynos5420, the STREAM_STAT bit raised on the JPGINTST register means there is a syntax error or an unrecoverable error on compressed file when ERR_INT_EN is set to 1. Fix this case and report BUF_STATE_ERROR to videobuf2. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 5ad3d43..c35d169 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2812,6 +2812,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) unsigned long payload_size = 0; enum vb2_buffer_state state = VB2_BUF_STATE_DONE; bool interrupt_timeout = false; + bool stream_error = false; u32 irq_status; spin_lock(>slock); @@ -2828,6 +2829,12 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) jpeg->irq_status |= irq_status; + if (jpeg->variant->version == SJPEG_EXYNOS5420 && + irq_status & EXYNOS3250_STREAM_STAT) { + stream_error = true; + dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n"); + } + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); if (!curr_ctx) @@ -2844,7 +2851,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) EXYNOS3250_RDMA_DONE | EXYNOS3250_RESULT_STAT)) payload_size = exynos3250_jpeg_compressed_size(jpeg->regs); - else if (interrupt_timeout) + else if (interrupt_timeout || stream_error) state = VB2_BUF_STATE_ERROR; else goto exit_unlock; -- 2.7.4
[PATCH v3 5/8] [media] s5p-jpeg: Split s5p_jpeg_parse_hdr()
This patch moves the subsampling value decoding read from the jpeg header into its own function. This new function is called s5p_jpeg_subsampling_decode() and returns true if it successfully decodes the subsampling value, false otherwise. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 42 - 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 1769744..0783809 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1096,6 +1096,29 @@ static void skip(struct s5p_jpeg_buffer *buf, long len) get_byte(buf); } +static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx, + unsigned int subsampling) +{ + switch (subsampling) { + case 0x11: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444; + break; + case 0x21: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422; + break; + case 0x22: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420; + break; + case 0x33: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; + break; + default: + return false; + } + + return true; +} + static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, unsigned long buffer, unsigned long size, struct s5p_jpeg_ctx *ctx) @@ -1207,26 +1230,9 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, } } - if (notfound || !sos) + if (notfound || !sos || !s5p_jpeg_subsampling_decode(ctx, subsampling)) return false; - switch (subsampling) { - case 0x11: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444; - break; - case 0x21: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422; - break; - case 0x22: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420; - break; - case 0x33: - ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; - break; - default: - return false; - } - result->w = width; result->h = height; result->sos = sos; -- 2.7.4
[PATCH v3 2/8] [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling
From: Tony K Nadackal <tony...@samsung.com> Corrects the WARN_ON statement for subsampling based on the JPEG Hardware version. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 623508d..0d935f5 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -614,24 +614,26 @@ static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) { - WARN_ON(ctx->subsampling > 3); - switch (ctx->jpeg->variant->version) { case SJPEG_S5P: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; return ctx->subsampling; case SJPEG_EXYNOS3250: case SJPEG_EXYNOS5420: + WARN_ON(ctx->subsampling > 6); if (ctx->subsampling > 3) return V4L2_JPEG_CHROMA_SUBSAMPLING_411; return exynos3250_decoded_subsampling[ctx->subsampling]; case SJPEG_EXYNOS4: case SJPEG_EXYNOS5433: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_420; return exynos4x12_decoded_subsampling[ctx->subsampling]; default: + WARN_ON(ctx->subsampling > 3); return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; } } -- 2.7.4
[PATCH v3 1/8] [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf
From: Tony K Nadackal <tony...@samsung.com> When queuing an OUTPUT buffer for decoder, s5p_jpeg_parse_hdr() function parses the input jpeg file and takes the width and height parameters from its header. These new width/height values will be used for the calculation of stride. HX_JPEG Hardware needs the width and height values aligned on a 16 bits boundary. This width/height alignment is handled in the s5p_jpeg_s_fmt_vid_cap() function during the S_FMT ioctl call. But if user space calls the QBUF of OUTPUT buffer after the S_FMT of CAPTURE buffer, these aligned values will be replaced by the values in jpeg header. If the width/height values of jpeg are not aligned, the decoder output will be corrupted. So in this patch we call jpeg_bound_align_image() to align the width/height values of Capture buffer in s5p_jpeg_buf_queue(). Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 52dc794..623508d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2523,6 +2523,25 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) q_data = >cap_q; q_data->w = tmp.w; q_data->h = tmp.h; + + /* +* This call to jpeg_bound_align_image() takes care of width and +* height values alignment when user space calls the QBUF of +* OUTPUT buffer after the S_FMT of CAPTURE buffer. +* Please note that on Exynos4x12 SoCs, resigning from executing +* S_FMT on capture buffer for each JPEG image can result in a +* hardware hangup if subsampling is lower than the one of input +* JPEG. +*/ + jpeg_bound_align_image(ctx, + _data->w, + S5P_JPEG_MIN_WIDTH, S5P_JPEG_MAX_WIDTH, + q_data->fmt->h_align, + _data->h, + S5P_JPEG_MIN_HEIGHT, S5P_JPEG_MAX_HEIGHT, + q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; } v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); -- 2.7.4
Re: [PATCH v2 5/6] [media] s5p-jpeg: Add support for resolution change event
Hi Andrzej, On 20/06/2017 12:51, Andrzej Pietrasiewicz wrote: Hi Thierry, W dniu 19.06.2017 o 15:50, Thierry Escande pisze: Hi Andrzej, On 16/06/2017 17:38, Andrzej Pietrasiewicz wrote: Hi Thierry, Thank you for the patch. Can you give a use case for resolution change event? Unfortunately, the original commit does not mention any clear use case. I've asked to the patch author for more information. Can you please share what you learn about it if the author gets back to you? Now that we don't know why to apply a patch I guess we should not do it. This event is used in Chromium by the V4L2 jpeg decode accelerator to allocate output buffer. Please see: https://cs.chromium.org/chromium/src/media/gpu/v4l2_jpeg_decode_accelerator.cc?rcl=91793c6ef94f05e93d258db8c7f3cad59819c6b8=585 I'll add a note in the commit message. @@ -2510,43 +2567,18 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) return; } -q_data = >out_q; -q_data->w = tmp.w; -q_data->h = tmp.h; -q_data->sos = tmp.sos; -memcpy(q_data->dht.marker, tmp.dht.marker, - sizeof(tmp.dht.marker)); -memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len)); -q_data->dht.n = tmp.dht.n; -memcpy(q_data->dqt.marker, tmp.dqt.marker, - sizeof(tmp.dqt.marker)); -memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len)); -q_data->dqt.n = tmp.dqt.n; -q_data->sof = tmp.sof; -q_data->sof_len = tmp.sof_len; - -q_data = >cap_q; -q_data->w = tmp.w; -q_data->h = tmp.h; Why is this part removed? This has not been removed. The s5p_jpeg_q_data struct was passed to s5p_jpeg_parse_hdr() and then copied field-by-field into ctx->out_q (through q_data pointer). With this change ctx->out_q is passed to s5p_jpeg_parse_hdr() and this avoids the copy. It seems that changing field-by-field copying to passing a pointer directly to s5p_jpeg_parse_hdr() is an unrelated change and as such should be in a separate patch. Will do. Regards, Thierry
Re: [PATCH v2 5/6] [media] s5p-jpeg: Add support for resolution change event
Hi Andrzej, On 16/06/2017 17:38, Andrzej Pietrasiewicz wrote: Hi Thierry, Thank you for the patch. Can you give a use case for resolution change event? Unfortunately, the original commit does not mention any clear use case. I've asked to the patch author for more information. Also plase see inline. W dniu 12.06.2017 o 19:13, Thierry Escande pisze: From: henryhsu <henry...@chromium.org> @@ -1611,8 +1612,6 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE; q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type); -q_data->w = pix->width; -q_data->h = pix->height; if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) { /* * During encoding Exynos4x12 SoCs access wider memory area @@ -1620,6 +1619,8 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu * page fault calculate proper buffer size in such a case. */ +q_data->w = pix->width; +q_data->h = pix->height; Is this change related to what the patch is supposed to be doing? Yes actually. From the author comments to the same question: "We want to send a resolution change in the first frame. Without this, q_data->w and h will be updated by s_fmt. Then we won't know the resolution is changed from (0, 0) to (w, h) in qbuf function." static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -2499,9 +2545,20 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) if (ctx->mode == S5P_JPEG_DECODE && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { -struct s5p_jpeg_q_data tmp, *q_data; - -ctx->hdr_parsed = s5p_jpeg_parse_hdr(, +static const struct v4l2_event ev_src_ch = { +.type = V4L2_EVENT_SOURCE_CHANGE, +.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, +}; +struct vb2_queue *dst_vq; +u32 ori_w; +u32 ori_h; + +dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); +ori_w = ctx->out_q.w; +ori_h = ctx->out_q.h; + +ctx->hdr_parsed = s5p_jpeg_parse_hdr(>out_q, (unsigned long)vb2_plane_vaddr(vb, 0), min((unsigned long)ctx->out_q.size, vb2_get_plane_payload(vb, 0)), ctx); @@ -2510,43 +2567,18 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) return; } -q_data = >out_q; -q_data->w = tmp.w; -q_data->h = tmp.h; -q_data->sos = tmp.sos; -memcpy(q_data->dht.marker, tmp.dht.marker, - sizeof(tmp.dht.marker)); -memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len)); -q_data->dht.n = tmp.dht.n; -memcpy(q_data->dqt.marker, tmp.dqt.marker, - sizeof(tmp.dqt.marker)); -memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len)); -q_data->dqt.n = tmp.dqt.n; -q_data->sof = tmp.sof; -q_data->sof_len = tmp.sof_len; - -q_data = >cap_q; -q_data->w = tmp.w; -q_data->h = tmp.h; Why is this part removed? This has not been removed. The s5p_jpeg_q_data struct was passed to s5p_jpeg_parse_hdr() and then copied field-by-field into ctx->out_q (through q_data pointer). With this change ctx->out_q is passed to s5p_jpeg_parse_hdr() and this avoids the copy. Then ctx->cap_q width & height copy is done in s5p_jpeg_set_capture_queue_data(). Regards, Thierry
[PATCH v2 6/6] [media] s5p-jpeg: Add stream error handling for Exynos5420
From: henryhsu <henry...@chromium.org> On Exynos5420, the STREAM_STAT bit raised on the JPGINTST register means there is a syntax error or an unrecoverable error on compressed file when ERR_INT_EN is set to 1. Fix this case and report BUF_STATE_ERROR to videobuf2. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 3d90a63..1a07a82 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2790,6 +2790,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) unsigned long payload_size = 0; enum vb2_buffer_state state = VB2_BUF_STATE_DONE; bool interrupt_timeout = false; + bool stream_error = false; u32 irq_status; spin_lock(>slock); @@ -2806,6 +2807,11 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) jpeg->irq_status |= irq_status; + if (irq_status & EXYNOS3250_STREAM_STAT) { + stream_error = true; + dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n"); + } + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); if (!curr_ctx) @@ -2822,7 +2828,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) EXYNOS3250_RDMA_DONE | EXYNOS3250_RESULT_STAT)) payload_size = exynos3250_jpeg_compressed_size(jpeg->regs); - else if (interrupt_timeout) + else if (interrupt_timeout || stream_error) state = VB2_BUF_STATE_ERROR; else goto exit_unlock; -- 2.7.4
[PATCH v2 3/6] [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling
From: Tony K Nadackal <tony...@samsung.com> Corrects the WARN_ON statement for subsampling based on the JPEG Hardware version. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 623508d..0d935f5 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -614,24 +614,26 @@ static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) { - WARN_ON(ctx->subsampling > 3); - switch (ctx->jpeg->variant->version) { case SJPEG_S5P: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; return ctx->subsampling; case SJPEG_EXYNOS3250: case SJPEG_EXYNOS5420: + WARN_ON(ctx->subsampling > 6); if (ctx->subsampling > 3) return V4L2_JPEG_CHROMA_SUBSAMPLING_411; return exynos3250_decoded_subsampling[ctx->subsampling]; case SJPEG_EXYNOS4: case SJPEG_EXYNOS5433: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_420; return exynos4x12_decoded_subsampling[ctx->subsampling]; default: + WARN_ON(ctx->subsampling > 3); return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; } } -- 2.7.4
[PATCH v2 0/6] [media] s5p-jpeg: Various fixes and improvements
Hi, This series contains various fixes and improvements for the Samsung s5p-jpeg driver. All these patches come from the Chromium v3.8 kernel tree. In this v2: - Remove IOMMU support patch (mapping now created automatically for single JPEG CODEC device). - Remove "Change sclk_jpeg to 166MHz" patch (can be set through DT properties). - Remove support for multi-planar APIs (Not needed). - Add comment regarding call to jpeg_bound_align_image() after qbuf. - Remove unrelated code from resolution change event support patch. Regards, Thierry Abhilash Kesavan (1): [media] s5p-jpeg: Reset the Codec before doing a soft reset Tony K Nadackal (3): [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format henryhsu (2): [media] s5p-jpeg: Add support for resolution change event [media] s5p-jpeg: Add stream error handling for Exynos5420 drivers/media/platform/s5p-jpeg/jpeg-core.c | 140 +- drivers/media/platform/s5p-jpeg/jpeg-core.h | 7 ++ drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c | 4 + 3 files changed, 122 insertions(+), 29 deletions(-) -- 2.7.4
[PATCH v2 5/6] [media] s5p-jpeg: Add support for resolution change event
From: henryhsu <henry...@chromium.org> This patch adds support for resolution change event to notify clients so they can prepare correct output buffer. When resolution change happened, G_FMT for CAPTURE should return old resolution and format before CAPTURE queues streamoff. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 125 +++- drivers/media/platform/s5p-jpeg/jpeg-core.h | 7 ++ 2 files changed, 91 insertions(+), 41 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 7ef7173..3d90a63 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1611,8 +1612,6 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE; q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type); - q_data->w = pix->width; - q_data->h = pix->height; if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) { /* * During encoding Exynos4x12 SoCs access wider memory area @@ -1620,6 +1619,8 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu * page fault calculate proper buffer size in such a case. */ + q_data->w = pix->width; + q_data->h = pix->height; if (ct->jpeg->variant->hw_ex4_compat && f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE) q_data->size = exynos4_jpeg_get_output_buffer_size(ct, @@ -1695,6 +1696,15 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); } +static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + if (sub->type == V4L2_EVENT_SOURCE_CHANGE) + return v4l2_src_change_event_subscribe(fh, sub); + + return -EINVAL; +} + static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, struct v4l2_rect *r) { @@ -2020,6 +2030,9 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { .vidioc_g_selection = s5p_jpeg_g_selection, .vidioc_s_selection = s5p_jpeg_s_selection, + + .vidioc_subscribe_event = s5p_jpeg_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* @@ -2412,8 +2425,17 @@ static int s5p_jpeg_job_ready(void *priv) { struct s5p_jpeg_ctx *ctx = priv; - if (ctx->mode == S5P_JPEG_DECODE) + if (ctx->mode == S5P_JPEG_DECODE) { + /* +* We have only one input buffer and one output buffer. If there +* is a resolution change event, no need to continue decoding. +*/ + if (ctx->state == JPEGCTX_RESOLUTION_CHANGE) + return 0; + return ctx->hdr_parsed; + } + return 1; } @@ -2492,6 +2514,30 @@ static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb) return 0; } +static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg_q_data *q_data = >cap_q; + + q_data->w = ctx->out_q.w; + q_data->h = ctx->out_q.h; + + /* +* This call to jpeg_bound_align_image() takes care of width and +* height values alignment when user space calls the QBUF of +* OUTPUT buffer after the S_FMT of CAPTURE buffer. +* Please note that on Exynos4x12 SoCs, resigning from executing +* S_FMT on capture buffer for each JPEG image can result in a +* hardware hangup if subsampling is lower than the one of input +* JPEG. +*/ + jpeg_bound_align_image(ctx, _data->w, S5P_JPEG_MIN_WIDTH, + S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align, + _data->h, S5P_JPEG_MIN_HEIGHT, + S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; +} + static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -2499,9 +2545,20 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) if (ctx->mode == S5P_JPEG_DECODE && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPU
[PATCH v2 4/6] [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format
From: Tony K Nadackal <tony...@samsung.com> This patch adds support for decoding 4:1:1 chroma subsampling in the jpeg header parsing function. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 0d935f5..7ef7173 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1236,6 +1236,9 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, case 0x33: ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; break; + case 0x41: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411; + break; default: return false; } -- 2.7.4
[PATCH v2 1/6] [media] s5p-jpeg: Reset the Codec before doing a soft reset
From: Abhilash Kesavan <a.kesa...@samsung.com> This patch resets the encoding and decoding register bits before doing a soft reset. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c index a1d823a..9ad8f6d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c @@ -21,6 +21,10 @@ void exynos4_jpeg_sw_reset(void __iomem *base) unsigned int reg; reg = readl(base + EXYNOS4_JPEG_CNTL_REG); + writel(reg & ~(EXYNOS4_DEC_MODE | EXYNOS4_ENC_MODE), + base + EXYNOS4_JPEG_CNTL_REG); + + reg = readl(base + EXYNOS4_JPEG_CNTL_REG); writel(reg & ~EXYNOS4_SOFT_RESET_HI, base + EXYNOS4_JPEG_CNTL_REG); udelay(100); -- 2.7.4
[PATCH v2 2/6] [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf
From: Tony K Nadackal <tony...@samsung.com> When queuing an OUTPUT buffer for decoder, s5p_jpeg_parse_hdr() function parses the input jpeg file and takes the width and height parameters from its header. These new width/height values will be used for the calculation of stride. HX_JPEG Hardware needs the width and height values aligned on a 16 bits boundary. This width/height alignment is handled in the s5p_jpeg_s_fmt_vid_cap() function during the S_FMT ioctl call. But if user space calls the QBUF of OUTPUT buffer after the S_FMT of CAPTURE buffer, these aligned values will be replaced by the values in jpeg header. If the width/height values of jpeg are not aligned, the decoder output will be corrupted. So in this patch we call jpeg_bound_align_image() to align the width/height values of Capture buffer in s5p_jpeg_buf_queue(). Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 52dc794..623508d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2523,6 +2523,25 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) q_data = >cap_q; q_data->w = tmp.w; q_data->h = tmp.h; + + /* +* This call to jpeg_bound_align_image() takes care of width and +* height values alignment when user space calls the QBUF of +* OUTPUT buffer after the S_FMT of CAPTURE buffer. +* Please note that on Exynos4x12 SoCs, resigning from executing +* S_FMT on capture buffer for each JPEG image can result in a +* hardware hangup if subsampling is lower than the one of input +* JPEG. +*/ + jpeg_bound_align_image(ctx, + _data->w, + S5P_JPEG_MIN_WIDTH, S5P_JPEG_MAX_WIDTH, + q_data->fmt->h_align, + _data->h, + S5P_JPEG_MIN_HEIGHT, S5P_JPEG_MAX_HEIGHT, + q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; } v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); -- 2.7.4
Re: [PATCH 6/9] [media] s5p-jpeg: Add support for resolution change event
Hi Jacek, On 02/06/2017 23:53, Jacek Anaszewski wrote: Hi Thierry, On 06/02/2017 06:02 PM, Thierry Escande wrote: From: henryhsu <henry...@chromium.org> This patch adds support for resolution change event to notify clients so they can prepare correct output buffer. When resolution change happened, G_FMT for CAPTURE should return old resolution and format before CAPTURE queues streamoff. Do you have a use case for that? Sorry but no. Again, the entry in the chromeos bug tracker does not mention any use case. --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c - pix->width = q_data->w; - pix->height = q_data->h; + if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && +ct->mode == S5P_JPEG_ENCODE) || + (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && +ct->mode == S5P_JPEG_DECODE)) { + pix->width = 0; + pix->height = 0; + } else { + pix->width = q_data->w; + pix->height = q_data->h; + } + Is this change related to the patch subject? Hum... Not sure indeed. I'll remove that from the v2. +static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg_q_data *q_data = >cap_q; + + q_data->w = ctx->out_q.w; + q_data->h = ctx->out_q.h; + + jpeg_bound_align_image(ctx, _data->w, S5P_JPEG_MIN_WIDTH, + S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align, + _data->h, S5P_JPEG_MIN_HEIGHT, + S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; +} + static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -2565,9 +2611,20 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) if (ctx->mode == S5P_JPEG_DECODE && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - struct s5p_jpeg_q_data tmp, *q_data; - - ctx->hdr_parsed = s5p_jpeg_parse_hdr(, + static const struct v4l2_event ev_src_ch = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, + }; + struct vb2_queue *dst_vq; + u32 ori_w; + u32 ori_h; + + dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, +V4L2_BUF_TYPE_VIDEO_CAPTURE); + ori_w = ctx->out_q.w; + ori_h = ctx->out_q.h; + + ctx->hdr_parsed = s5p_jpeg_parse_hdr(>out_q, (unsigned long)vb2_plane_vaddr(vb, 0), min((unsigned long)ctx->out_q.size, vb2_get_plane_payload(vb, 0)), ctx); @@ -2576,31 +2633,18 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) return; } - q_data = >out_q; - q_data->w = tmp.w; - q_data->h = tmp.h; - q_data->sos = tmp.sos; - memcpy(q_data->dht.marker, tmp.dht.marker, - sizeof(tmp.dht.marker)); - memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len)); - q_data->dht.n = tmp.dht.n; - memcpy(q_data->dqt.marker, tmp.dqt.marker, - sizeof(tmp.dqt.marker)); - memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len)); - q_data->dqt.n = tmp.dqt.n; - q_data->sof = tmp.sof; - q_data->sof_len = tmp.sof_len; You're removing here quantization and Huffman table info, is it intentional? ctx->out_q is now passed directly to s5p_jpeg_parse_hdr(). This avoids this field-by-field copy already done in s5p_jpeg_parse_hdr(). This do not remove anything unless I'm missing something here... Regards, Thierry
Re: [PATCH 1/9] [media] s5p-jpeg: Reset the Codec before doing a soft reset
Hi Jacek, On 02/06/2017 21:50, Jacek Anaszewski wrote: Hi Thierry, On 06/02/2017 06:02 PM, Thierry Escande wrote: From: Abhilash Kesavan <a.kesa...@samsung.com> This patch resets the encoding and decoding register bits before doing a soft reset. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c index a1d823a..9ad8f6d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c @@ -21,6 +21,10 @@ void exynos4_jpeg_sw_reset(void __iomem *base) unsigned int reg; reg = readl(base + EXYNOS4_JPEG_CNTL_REG); + writel(reg & ~(EXYNOS4_DEC_MODE | EXYNOS4_ENC_MODE), + base + EXYNOS4_JPEG_CNTL_REG); Why is it required? It would be nice if commit message explained that. Unfortunately the bug entry in the ChromeOS issue tracker does not mention more information about that and the patch author is no more reachable on that email address. So unless someone else knows the answer I won't be able to give more explanation in the commit message... Regards, Thierry
[PATCH 4/9] [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format
From: Tony K Nadackal <tony...@samsung.com> This patch adds support for decoding 4:1:1 chroma subsampling in the jpeg header parsing function. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 0d83948..770a709 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1236,6 +1236,9 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, case 0x33: ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; break; + case 0x41: + ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411; + break; default: return false; } -- 2.7.4
[PATCH 0/9] [media] s5p-jpeg: Various fixes and improvements
Hi, This series contains various fixes and improvements for the Samsung s5p-jpeg driver. All these patches come from the Chromium v3.8 kernel tree. Regards, Thierry Abhilash Kesavan (1): [media] s5p-jpeg: Reset the Codec before doing a soft reset Ricky Liang (1): [media] s5p-jpeg: Add support for multi-planar APIs Tony K Nadackal (4): [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling [media] s5p-jpeg: Decode 4:1:1 chroma subsampling format [media] s5p-jpeg: Add IOMMU support henryhsu (3): [media] s5p-jpeg: Add support for resolution change event [media] s5p-jpeg: Change sclk_jpeg to 166MHz for Exynos5250 [media] s5p-jpeg: Add stream error handling for Exynos5420 drivers/media/platform/s5p-jpeg/jpeg-core.c | 387 -- drivers/media/platform/s5p-jpeg/jpeg-core.h | 9 + drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c | 4 + 3 files changed, 368 insertions(+), 32 deletions(-) -- 2.7.4
[PATCH 1/9] [media] s5p-jpeg: Reset the Codec before doing a soft reset
From: Abhilash Kesavan <a.kesa...@samsung.com> This patch resets the encoding and decoding register bits before doing a soft reset. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c index a1d823a..9ad8f6d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c @@ -21,6 +21,10 @@ void exynos4_jpeg_sw_reset(void __iomem *base) unsigned int reg; reg = readl(base + EXYNOS4_JPEG_CNTL_REG); + writel(reg & ~(EXYNOS4_DEC_MODE | EXYNOS4_ENC_MODE), + base + EXYNOS4_JPEG_CNTL_REG); + + reg = readl(base + EXYNOS4_JPEG_CNTL_REG); writel(reg & ~EXYNOS4_SOFT_RESET_HI, base + EXYNOS4_JPEG_CNTL_REG); udelay(100); -- 2.7.4
[PATCH 2/9] [media] s5p-jpeg: Call jpeg_bound_align_image after qbuf
From: Tony K Nadackal <tony...@samsung.com> When queuing an OUTPUT buffer for decoder, s5p_jpeg_parse_hdr() function parses the input jpeg file and takes the width and height parameters from its header. These new width/height values will be used for the calculation of stride. HX_JPEG Hardware needs the width and height values aligned on a 16 bits boundary. This width/height alignment is handled in the s5p_jpeg_s_fmt_vid_cap() function during the S_FMT ioctl call. But if user space calls the QBUF of OUTPUT buffer after the S_FMT of CAPTURE buffer, these aligned values will be replaced by the values in jpeg header. If the width/height values of jpeg are not aligned, the decoder output will be corrupted. So in this patch we call jpeg_bound_align_image() to align the width/height values of Capture buffer in s5p_jpeg_buf_queue(). Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 52dc794..6fb1ab4 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2523,6 +2523,13 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) q_data = >cap_q; q_data->w = tmp.w; q_data->h = tmp.h; + + jpeg_bound_align_image(ctx, _data->w, S5P_JPEG_MIN_WIDTH, + S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align, + _data->h, S5P_JPEG_MIN_HEIGHT, + S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align + ); + q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; } v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); -- 2.7.4
[PATCH 5/9] [media] s5p-jpeg: Add IOMMU support
From: Tony K Nadackal <tony...@samsung.com> This patch adds support for IOMMU s5p-jpeg driver if the Exynos IOMMU and ARM DMA IOMMU configurations are supported. The address space is created with size limited to 256M and base address set to 0x2000. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 77 + 1 file changed, 77 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 770a709..5569b99 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -28,6 +28,14 @@ #include #include #include +#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) +#include +#include +#include +#include +#include +#include +#endif #include "jpeg-core.h" #include "jpeg-hw-s5p.h" @@ -35,6 +43,10 @@ #include "jpeg-hw-exynos3250.h" #include "jpeg-regs.h" +#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) +static struct dma_iommu_mapping *mapping; +#endif + static struct s5p_jpeg_fmt sjpeg_formats[] = { { .name = "JPEG JFIF", @@ -956,6 +968,60 @@ static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx) } } +#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) +static int jpeg_iommu_init(struct platform_device *pdev) +{ + struct device *dev = >dev; + int err; + + mapping = arm_iommu_create_mapping(_bus_type, 0x2000, + SZ_512M); + if (IS_ERR(mapping)) { + dev_err(dev, "IOMMU mapping failed\n"); + return PTR_ERR(mapping); + } + + dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL); + if (!dev->dma_parms) { + err = -ENOMEM; + goto error_alloc; + } + + err = dma_set_max_seg_size(dev, 0xu); + if (err) + goto error; + + err = arm_iommu_attach_device(dev, mapping); + if (err) + goto error; + + return 0; + +error: + devm_kfree(dev, dev->dma_parms); + dev->dma_parms = NULL; + +error_alloc: + arm_iommu_release_mapping(mapping); + mapping = NULL; + + return err; +} + +static void jpeg_iommu_deinit(struct platform_device *pdev) +{ + struct device *dev = >dev; + + if (mapping) { + arm_iommu_detach_device(dev); + devm_kfree(dev, dev->dma_parms); + dev->dma_parms = NULL; + arm_iommu_release_mapping(mapping); + mapping = NULL; + } +} +#endif + /* * * Device file operations @@ -2816,6 +2882,13 @@ static int s5p_jpeg_probe(struct platform_device *pdev) spin_lock_init(>slock); jpeg->dev = >dev; +#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) + ret = jpeg_iommu_init(pdev); + if (ret) { + dev_err(>dev, "IOMMU Initialization failed\n"); + return ret; + } +#endif /* memory-mapped registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2962,6 +3035,10 @@ static int s5p_jpeg_remove(struct platform_device *pdev) clk_disable_unprepare(jpeg->clocks[i]); } +#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) + jpeg_iommu_deinit(pdev); +#endif + return 0; } -- 2.7.4
[PATCH 6/9] [media] s5p-jpeg: Add support for resolution change event
From: henryhsu <henry...@chromium.org> This patch adds support for resolution change event to notify clients so they can prepare correct output buffer. When resolution change happened, G_FMT for CAPTURE should return old resolution and format before CAPTURE queues streamoff. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 121 drivers/media/platform/s5p-jpeg/jpeg-core.h | 7 ++ 2 files changed, 95 insertions(+), 33 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 5569b99..7a7acbc 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1416,8 +1417,17 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) q_data = get_q_data(ct, f->type); BUG_ON(q_data == NULL); - pix->width = q_data->w; - pix->height = q_data->h; + if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && +ct->mode == S5P_JPEG_ENCODE) || + (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && +ct->mode == S5P_JPEG_DECODE)) { + pix->width = 0; + pix->height = 0; + } else { + pix->width = q_data->w; + pix->height = q_data->h; + } + pix->field = V4L2_FIELD_NONE; pix->pixelformat = q_data->fmt->fourcc; pix->bytesperline = 0; @@ -1677,8 +1687,6 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE; q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type); - q_data->w = pix->width; - q_data->h = pix->height; if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) { /* * During encoding Exynos4x12 SoCs access wider memory area @@ -1686,6 +1694,8 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu * page fault calculate proper buffer size in such a case. */ + q_data->w = pix->width; + q_data->h = pix->height; if (ct->jpeg->variant->hw_ex4_compat && f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE) q_data->size = exynos4_jpeg_get_output_buffer_size(ct, @@ -1761,6 +1771,15 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); } +static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + if (sub->type == V4L2_EVENT_SOURCE_CHANGE) + return v4l2_src_change_event_subscribe(fh, sub); + + return -EINVAL; +} + static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, struct v4l2_rect *r) { @@ -2086,6 +2105,9 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { .vidioc_g_selection = s5p_jpeg_g_selection, .vidioc_s_selection = s5p_jpeg_s_selection, + + .vidioc_subscribe_event = s5p_jpeg_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* @@ -2478,8 +2500,17 @@ static int s5p_jpeg_job_ready(void *priv) { struct s5p_jpeg_ctx *ctx = priv; - if (ctx->mode == S5P_JPEG_DECODE) + if (ctx->mode == S5P_JPEG_DECODE) { + /* +* We have only one input buffer and one output buffer. If there +* is a resolution change event, no need to continue decoding. +*/ + if (ctx->state == JPEGCTX_RESOLUTION_CHANGE) + return 0; + return ctx->hdr_parsed; + } + return 1; } @@ -2558,6 +2589,21 @@ static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb) return 0; } +static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx) +{ + struct s5p_jpeg_q_data *q_data = >cap_q; + + q_data->w = ctx->out_q.w; + q_data->h = ctx->out_q.h; + + jpeg_bound_align_image(ctx, _data->w, S5P_JPEG_MIN_WIDTH, + S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align, + _data->h, S5P_JPEG_MIN_HEIGHT, + S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align); + + q_data->size = q_data->w * q_data->h * q_data-&
[PATCH 8/9] [media] s5p-jpeg: Add stream error handling for Exynos5420
From: henryhsu <henry...@chromium.org> On Exynos5420, the STREAM_STAT bit raised on the JPGINTST register means there is a syntax error or an unrecoverable error on compressed file when ERR_INT_EN is set to 1. Fix this case and report BUF_STATE_ERROR to videobuf2. Signed-off-by: Henry-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 430e925..db56135 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2894,6 +2894,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) unsigned long payload_size = 0; enum vb2_buffer_state state = VB2_BUF_STATE_DONE; bool interrupt_timeout = false; + bool stream_error = false; u32 irq_status; spin_lock(>slock); @@ -2910,6 +2911,11 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) jpeg->irq_status |= irq_status; + if (irq_status & EXYNOS3250_STREAM_STAT) { + stream_error = true; + dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n"); + } + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); if (!curr_ctx) @@ -2926,7 +2932,7 @@ static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) EXYNOS3250_RDMA_DONE | EXYNOS3250_RESULT_STAT)) payload_size = exynos3250_jpeg_compressed_size(jpeg->regs); - else if (interrupt_timeout) + else if (interrupt_timeout || stream_error) state = VB2_BUF_STATE_ERROR; else goto exit_unlock; -- 2.7.4
[PATCH 7/9] [media] s5p-jpeg: Change sclk_jpeg to 166MHz for Exynos5250
From: henryhsu <henry...@chromium.org> The default clock parent of jpeg on Exynos5250 is fin_pll, which is 24MHz. We have to change the clock parent to CPLL, which is 333MHz, and set sclk_jpeg to 166MHz. Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 47 + 1 file changed, 47 insertions(+) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 7a7acbc..430e925 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -969,6 +969,44 @@ static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx) } } +static int exynos4_jpeg_set_sclk_rate(struct s5p_jpeg *jpeg, struct clk *sclk) +{ + struct clk *mout_jpeg; + struct clk *sclk_cpll; + int ret; + + mout_jpeg = clk_get(jpeg->dev, "mout_jpeg"); + if (IS_ERR(mout_jpeg)) { + dev_err(jpeg->dev, "mout_jpeg clock not available: %ld\n", + PTR_ERR(mout_jpeg)); + return PTR_ERR(mout_jpeg); + } + + sclk_cpll = clk_get(jpeg->dev, "sclk_cpll"); + if (IS_ERR(sclk_cpll)) { + dev_err(jpeg->dev, "sclk_cpll clock not available: %ld\n", + PTR_ERR(sclk_cpll)); + clk_put(mout_jpeg); + return PTR_ERR(sclk_cpll); + } + + ret = clk_set_parent(mout_jpeg, sclk_cpll); + clk_put(sclk_cpll); + clk_put(mout_jpeg); + if (ret) { + dev_err(jpeg->dev, "clk_set_parent failed: %d\n", ret); + return ret; + } + + ret = clk_set_rate(sclk, 166500 * 1000); + if (ret) { + dev_err(jpeg->dev, "clk_set_rate failed: %d\n", ret); + return ret; + } + + return 0; +} + #if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) static int jpeg_iommu_init(struct platform_device *pdev) { @@ -2974,6 +3012,15 @@ static int s5p_jpeg_probe(struct platform_device *pdev) jpeg->variant->clk_names[i]); return PTR_ERR(jpeg->clocks[i]); } + + if (jpeg->variant->version == SJPEG_EXYNOS4 && + !strncmp(jpeg->variant->clk_names[i], +"sclk", strlen("sclk"))) { + ret = exynos4_jpeg_set_sclk_rate(jpeg, +jpeg->clocks[i]); + if (ret) + return ret; + } } /* v4l2 device */ -- 2.7.4
[PATCH 9/9] [media] s5p-jpeg: Add support for multi-planar APIs
From: Ricky Liang <jcli...@chromium.org> This patch adds multi-planar APIs to the s5p-jpeg driver. The multi-planar APIs are identical to the exisiting single-planar APIs except the plane format info is stored in the v4l2_pixel_format_mplan struct instead of the v4l2_pixel_format struct. Signed-off-by: Ricky Liang <jcli...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 152 +--- drivers/media/platform/s5p-jpeg/jpeg-core.h | 2 + 2 files changed, 139 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index db56135..a8fd7ed 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1371,6 +1371,15 @@ static int s5p_jpeg_querycap(struct file *file, void *priv, dev_name(ctx->jpeg->dev)); cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + /* +* Advertise multi-planar capabilities. The driver supports only +* single-planar pixel format at this moment so all the buffers will +* have only one plane. +*/ + cap->capabilities |= V4L2_CAP_VIDEO_M2M_MPLANE | +V4L2_CAP_VIDEO_CAPTURE_MPLANE | +V4L2_CAP_VIDEO_OUTPUT_MPLANE; + return 0; } @@ -1430,12 +1439,10 @@ static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx, enum v4l2_buf_type type) { - if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (V4L2_TYPE_IS_OUTPUT(type)) return >out_q; - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return >cap_q; - return NULL; + return >cap_q; } static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) @@ -1449,16 +1456,14 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) if (!vq) return -EINVAL; - if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && + if (!V4L2_TYPE_IS_OUTPUT(f->type) && ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed) return -EINVAL; q_data = get_q_data(ct, f->type); BUG_ON(q_data == NULL); - if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && -ct->mode == S5P_JPEG_ENCODE) || - (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && -ct->mode == S5P_JPEG_DECODE)) { + if ((!V4L2_TYPE_IS_OUTPUT(f->type) && ct->mode == S5P_JPEG_ENCODE) || + (V4L2_TYPE_IS_OUTPUT(f->type) && ct->mode == S5P_JPEG_DECODE)) { pix->width = 0; pix->height = 0; } else { @@ -1715,6 +1720,8 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) q_data = get_q_data(ct, f->type); BUG_ON(q_data == NULL); + vq->type = f->type; + q_data->type = f->type; if (vb2_is_busy(vq)) { v4l2_err(>jpeg->v4l2_dev, "%s queue busy\n", __func__); @@ -1919,7 +1926,9 @@ static int s5p_jpeg_g_selection(struct file *file, void *priv, struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && + s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; /* For JPEG blob active == default == bounds */ @@ -1957,7 +1966,8 @@ static int s5p_jpeg_s_selection(struct file *file, void *fh, struct v4l2_rect *rect = >r; int ret = -EINVAL; - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; if (s->target == V4L2_SEL_TGT_COMPOSE) { @@ -2118,6 +2128,107 @@ static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx) return ret; } +static void v4l2_format_pixmp_to_pix(struct v4l2_format *fmt_pix_mp, +struct v4l2_format *fmt_pix) { + struct v4l2_pix_format *pix = _pix->fmt.pix; + struct v4l2_pix_format_mplane *pix_mp = _pix_mp->fmt.pix_mp; + + fmt_pix->type = fmt_pix_mp->type; + pix->width = pix_mp->width; + pix->height = pix_mp->height; + pix->pixelformat = pix_mp->pixelformat; +
[PATCH 3/9] [media] s5p-jpeg: Correct WARN_ON statement for checking subsampling
From: Tony K Nadackal <tony...@samsung.com> Corrects the WARN_ON statement for subsampling based on the JPEG Hardware version. Signed-off-by: Tony K Nadackal <tony...@samsung.com> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 6fb1ab4..0d83948 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -614,24 +614,26 @@ static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) { - WARN_ON(ctx->subsampling > 3); - switch (ctx->jpeg->variant->version) { case SJPEG_S5P: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; return ctx->subsampling; case SJPEG_EXYNOS3250: case SJPEG_EXYNOS5420: + WARN_ON(ctx->subsampling > 6); if (ctx->subsampling > 3) return V4L2_JPEG_CHROMA_SUBSAMPLING_411; return exynos3250_decoded_subsampling[ctx->subsampling]; case SJPEG_EXYNOS4: case SJPEG_EXYNOS5433: + WARN_ON(ctx->subsampling > 3); if (ctx->subsampling > 2) return V4L2_JPEG_CHROMA_SUBSAMPLING_420; return exynos4x12_decoded_subsampling[ctx->subsampling]; default: + WARN_ON(ctx->subsampling > 3); return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; } } -- 2.7.4
[PATCH v2] [media] v4l2: Add support for go2001 PCI codec driver
This patch adds support for the go2001 PCI codec driver. This hardware is present on ChromeOS based devices like the Acer ChromeBox and Acer/LG ChromeBase 24 devices. This driver comes from the ChromeOS v3.18 kernel tree and has been modified to support vb2_buffer restructuring introduced in Linux v4.4. This driver is originally developed by: Pawel Osciak <posc...@chromium.org> Ville-Mikko Rautio <v...@chromium.org> henryhsu <henry...@chromium.org> Wu-Cheng Li <wuchen...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- Changes in v2: - Removed unneeded call to dma_cache_sync() on coherent dma buffer. drivers/media/pci/Kconfig|2 + drivers/media/pci/Makefile |1 + drivers/media/pci/go2001/Kconfig | 11 + drivers/media/pci/go2001/Makefile|2 + drivers/media/pci/go2001/go2001.h| 331 drivers/media/pci/go2001/go2001_driver.c | 2563 ++ drivers/media/pci/go2001/go2001_hw.c | 1362 drivers/media/pci/go2001/go2001_hw.h | 55 + drivers/media/pci/go2001/go2001_proto.h | 359 + 9 files changed, 4686 insertions(+) create mode 100644 drivers/media/pci/go2001/Kconfig create mode 100644 drivers/media/pci/go2001/Makefile create mode 100644 drivers/media/pci/go2001/go2001.h create mode 100644 drivers/media/pci/go2001/go2001_driver.c create mode 100644 drivers/media/pci/go2001/go2001_hw.c create mode 100644 drivers/media/pci/go2001/go2001_hw.h create mode 100644 drivers/media/pci/go2001/go2001_proto.h diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig index da28e68..837681e 100644 --- a/drivers/media/pci/Kconfig +++ b/drivers/media/pci/Kconfig @@ -54,5 +54,7 @@ source "drivers/media/pci/smipcie/Kconfig" source "drivers/media/pci/netup_unidvb/Kconfig" endif +source "drivers/media/pci/go2001/Kconfig" + endif #MEDIA_PCI_SUPPORT endif #PCI diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile index a7e8af0..58639b7 100644 --- a/drivers/media/pci/Makefile +++ b/drivers/media/pci/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_STA2X11_VIP) += sta2x11/ obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ obj-$(CONFIG_VIDEO_COBALT) += cobalt/ obj-$(CONFIG_VIDEO_TW5864) += tw5864/ +obj-$(CONFIG_VIDEO_GO2001) += go2001/ diff --git a/drivers/media/pci/go2001/Kconfig b/drivers/media/pci/go2001/Kconfig new file mode 100644 index 000..c7b5149 --- /dev/null +++ b/drivers/media/pci/go2001/Kconfig @@ -0,0 +1,11 @@ +config VIDEO_GO2001 + tristate "GO2001 codec driver" + depends on VIDEO_V4L2 && PCI + select VIDEOBUF2_DMA_SG + ---help--- + This driver supports the GO2001 PCI hardware codec. This codec + is present on ChromeOS based devices like the Acer ChromeBox + and ChromeBase 24 and LG ChromeBase as well. + + To compile this driver as a module, choose M here: the + module will be called go2001. diff --git a/drivers/media/pci/go2001/Makefile b/drivers/media/pci/go2001/Makefile new file mode 100644 index 000..20bad18 --- /dev/null +++ b/drivers/media/pci/go2001/Makefile @@ -0,0 +1,2 @@ +go2001-objs:= go2001_driver.o go2001_hw.o +obj-$(CONFIG_VIDEO_GO2001) += go2001.o diff --git a/drivers/media/pci/go2001/go2001.h b/drivers/media/pci/go2001/go2001.h new file mode 100644 index 000..0e5ccfd --- /dev/null +++ b/drivers/media/pci/go2001/go2001.h @@ -0,0 +1,331 @@ +/* + * go2001 - GO2001 codec driver. + * + * Author : Pawel Osciak <posc...@chromium.org> + * + * Copyright (C) 2017 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _MEDIA_PCI_GO2001_GO2001_H_ +#define _MEDIA_PCI_GO2001_GO2001_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "go2001_proto.h" + +struct go2001_msg { + struct list_head list_entry; + struct go2001_msg_payload payload; +}; + +static inline struct go2001_msg_hdr *msg_to_hdr(struct go2001_msg *msg) +{ + return >payload.hdr; +} + +static inline void *msg_to_param(struct go2001_msg *msg) +{ + return msg->payload.param; +} + +struct go2001_msg_ring { + struct go2001_msg_ring_desc desc;
[PATCH] [media] v4l2: Add support for go2001 PCI codec driver
This patch adds support for the go2001 PCI codec driver. This hardware is present on ChromeOS based devices like the Acer ChromeBox and Acer/LG ChromeBase 24 devices. This driver comes from the ChromeOS v3.18 kernel tree and has been modified to support vb2_buffer restructuring introduced in Linux v4.4. This driver is originally developed by: Pawel Osciak <posc...@chromium.org> Ville-Mikko Rautio <v...@chromium.org> henryhsu <henry...@chromium.org> Wu-Cheng Li <wuchen...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/pci/Kconfig|2 + drivers/media/pci/Makefile |1 + drivers/media/pci/go2001/Kconfig | 11 + drivers/media/pci/go2001/Makefile|2 + drivers/media/pci/go2001/go2001.h| 331 drivers/media/pci/go2001/go2001_driver.c | 2563 ++ drivers/media/pci/go2001/go2001_hw.c | 1365 drivers/media/pci/go2001/go2001_hw.h | 55 + drivers/media/pci/go2001/go2001_proto.h | 359 + 9 files changed, 4689 insertions(+) create mode 100644 drivers/media/pci/go2001/Kconfig create mode 100644 drivers/media/pci/go2001/Makefile create mode 100644 drivers/media/pci/go2001/go2001.h create mode 100644 drivers/media/pci/go2001/go2001_driver.c create mode 100644 drivers/media/pci/go2001/go2001_hw.c create mode 100644 drivers/media/pci/go2001/go2001_hw.h create mode 100644 drivers/media/pci/go2001/go2001_proto.h diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig index da28e68..837681e 100644 --- a/drivers/media/pci/Kconfig +++ b/drivers/media/pci/Kconfig @@ -54,5 +54,7 @@ source "drivers/media/pci/smipcie/Kconfig" source "drivers/media/pci/netup_unidvb/Kconfig" endif +source "drivers/media/pci/go2001/Kconfig" + endif #MEDIA_PCI_SUPPORT endif #PCI diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile index a7e8af0..58639b7 100644 --- a/drivers/media/pci/Makefile +++ b/drivers/media/pci/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_STA2X11_VIP) += sta2x11/ obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ obj-$(CONFIG_VIDEO_COBALT) += cobalt/ obj-$(CONFIG_VIDEO_TW5864) += tw5864/ +obj-$(CONFIG_VIDEO_GO2001) += go2001/ diff --git a/drivers/media/pci/go2001/Kconfig b/drivers/media/pci/go2001/Kconfig new file mode 100644 index 000..c7b5149 --- /dev/null +++ b/drivers/media/pci/go2001/Kconfig @@ -0,0 +1,11 @@ +config VIDEO_GO2001 + tristate "GO2001 codec driver" + depends on VIDEO_V4L2 && PCI + select VIDEOBUF2_DMA_SG + ---help--- + This driver supports the GO2001 PCI hardware codec. This codec + is present on ChromeOS based devices like the Acer ChromeBox + and ChromeBase 24 and LG ChromeBase as well. + + To compile this driver as a module, choose M here: the + module will be called go2001. diff --git a/drivers/media/pci/go2001/Makefile b/drivers/media/pci/go2001/Makefile new file mode 100644 index 000..20bad18 --- /dev/null +++ b/drivers/media/pci/go2001/Makefile @@ -0,0 +1,2 @@ +go2001-objs:= go2001_driver.o go2001_hw.o +obj-$(CONFIG_VIDEO_GO2001) += go2001.o diff --git a/drivers/media/pci/go2001/go2001.h b/drivers/media/pci/go2001/go2001.h new file mode 100644 index 000..0e5ccfd --- /dev/null +++ b/drivers/media/pci/go2001/go2001.h @@ -0,0 +1,331 @@ +/* + * go2001 - GO2001 codec driver. + * + * Author : Pawel Osciak <posc...@chromium.org> + * + * Copyright (C) 2017 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _MEDIA_PCI_GO2001_GO2001_H_ +#define _MEDIA_PCI_GO2001_GO2001_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "go2001_proto.h" + +struct go2001_msg { + struct list_head list_entry; + struct go2001_msg_payload payload; +}; + +static inline struct go2001_msg_hdr *msg_to_hdr(struct go2001_msg *msg) +{ + return >payload.hdr; +} + +static inline void *msg_to_param(struct go2001_msg *msg) +{ + return msg->payload.param; +} + +struct go2001_msg_ring { + struct go2001_msg_ring_desc desc; + void __iomem *desc_iomem; + void __iomem *data_iomem; + spi
Re: [PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag
Hi Mauro, On 18/11/2016 19:59, Mauro Carvalho Chehab wrote: Em Tue, 25 Oct 2016 10:22:29 +0200 Thierry Escande <thierry.esca...@collabora.com> escreveu: From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues as we don't want to allow HW to be able to write to OUTPUT buffers. This patch introduces 2 macros: VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue type, tanking care of the capture_dma_birectional flag. VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA direction refers to a capture buffer. This test is used to map virtual addresses for writing and to mark pages as dirty. Why to add it? There's no other patch on this series with would justify its needs... It is used by a Rockchip vpu driver which is only in the chromeos public tree for now and will be upstreamed soon. Regards, Thierry Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- Changes in v2: - Renamed use_dma_bidirectional field as capture_dma_bidirectional - Added a VB2_DMA_DIR() macro Changes in v3: - Get rid of dma_dir field and therefore squashed the previous patch Changes in v4: - Fixed typos in include/media/videobuf2-core.h - Added VB2_DMA_DIR_CAPTURE() test macro Changes in v5: - Use is_output queue field in VB2_DMA_DIR() macro drivers/media/v4l2-core/videobuf2-core.c | 9 +++-- drivers/media/v4l2-core/videobuf2-dma-contig.c | 2 +- drivers/media/v4l2-core/videobuf2-dma-sg.c | 5 +++-- drivers/media/v4l2-core/videobuf2-vmalloc.c| 4 ++-- include/media/videobuf2-core.h | 23 +++ 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..22d6105 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); void *mem_priv; int plane; int ret = -ENOMEM; @@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index fb6a177..a44e383 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, buf->dma_dir = dma_dir; offset = vaddr & ~PAGE_MASK; - vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE); + vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir)); if (IS_ERR(vec)) { ret = PTR_ERR(vec); goto fail_buf; diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index ecff8f49..51c98f6 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, buf->offset = vaddr & ~PAGE_MASK; buf->size = size; buf->dma_sgt = >sg_table; - vec = vb2_create_framevec(vaddr, size, bu
[PATCH v3 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks
This patch moves vb2_dc_get_base_sgt() function above mmap buffers callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it will be called for cacheable MMAP support introduced in the next patch. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index a44e383..0d9665d 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt) return size; } +static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) +{ + int ret; + struct sg_table *sgt; + + sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + dev_err(buf->dev, "failed to alloc sg table\n"); + return NULL; + } + + ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr, + buf->size, buf->attrs); + if (ret < 0) { + dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); + kfree(sgt); + return NULL; + } + + return sgt; +} + /*/ /* callbacks for all buffers */ /*/ @@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = { .release = vb2_dc_dmabuf_ops_release, }; -static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) -{ - int ret; - struct sg_table *sgt; - - sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); - if (!sgt) { - dev_err(buf->dev, "failed to alloc sg table\n"); - return NULL; - } - - ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr, - buf->size, buf->attrs); - if (ret < 0) { - dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); - kfree(sgt); - return NULL; - } - - return sgt; -} - static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags) { struct vb2_dc_buf *buf = buf_priv; -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/2] [media] videobuf2-dc: Add support for cacheable MMAP
Hi, This series adds support for cacheable MMAP in DMA coherent allocator. The first patch moves the vb2_dc_get_base_sgt() function above mmap callbacks for calls introduced by the second patch. This avoids a forward declaration. Changes in v2: - Put function move in a separate patch - Added comments Changes in v3: - Remove redundant test on NO_KERNEL_MAPPING DMA attribute in mmap() Heng-Ruey Hsu (1): [media] videobuf2-dc: Support cacheable MMAP Thierry Escande (1): [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks drivers/media/v4l2-core/videobuf2-dma-contig.c | 60 -- 1 file changed, 38 insertions(+), 22 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/2] [media] videobuf2-dc: Support cacheable MMAP
From: Heng-Ruey Hsu <henry...@chromium.org> DMA allocations for MMAP type are uncached by default. But for some cases, CPU has to access the buffers. ie: memcpy for format converter. Supporting cacheable MMAP improves huge performance. This patch enables cacheable memory for DMA coherent allocator in mmap buffer allocation if non-consistent DMA attribute is set and kernel mapping is present. Even if userspace doesn't mmap the buffer, sync still should be happening if kernel mapping is present. If not done in allocation, it is enabled when memory is mapped from userspace (if non-consistent DMA attribute is set). Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org> Tested-by: Heng-ruey Hsu <henry...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-dma-contig.c | 16 1 file changed, 16 insertions(+) diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 0d9665d..89b534a 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv) sg_free_table(buf->sgt_base); kfree(buf->sgt_base); } + if (buf->dma_sgt) { + sg_free_table(buf->dma_sgt); + kfree(buf->dma_sgt); + } dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, buf->attrs); put_device(buf->dev); @@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, buf->handler.put = vb2_dc_put; buf->handler.arg = buf; + /* +* Enable cache maintenance. Even if userspace doesn't mmap the buffer, +* sync still should be happening if kernel mapping is present. +*/ + if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) && + buf->attrs & DMA_ATTR_NON_CONSISTENT) + buf->dma_sgt = vb2_dc_get_base_sgt(buf); + atomic_inc(>refcount); return buf; @@ -227,6 +239,10 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma) vma->vm_ops->open(vma); + /* Enable cache maintenance if not enabled in allocation. */ + if (!buf->dma_sgt && buf->attrs & DMA_ATTR_NON_CONSISTENT) + buf->dma_sgt = vb2_dc_get_base_sgt(buf); + pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n", __func__, (unsigned long)buf->dma_addr, vma->vm_start, buf->size); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag
From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues as we don't want to allow HW to be able to write to OUTPUT buffers. This patch introduces 2 macros: VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue type, tanking care of the capture_dma_birectional flag. VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA direction refers to a capture buffer. This test is used to map virtual addresses for writing and to mark pages as dirty. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- Changes in v2: - Renamed use_dma_bidirectional field as capture_dma_bidirectional - Added a VB2_DMA_DIR() macro Changes in v3: - Get rid of dma_dir field and therefore squashed the previous patch Changes in v4: - Fixed typos in include/media/videobuf2-core.h - Added VB2_DMA_DIR_CAPTURE() test macro Changes in v5: - Use is_output queue field in VB2_DMA_DIR() macro drivers/media/v4l2-core/videobuf2-core.c | 9 +++-- drivers/media/v4l2-core/videobuf2-dma-contig.c | 2 +- drivers/media/v4l2-core/videobuf2-dma-sg.c | 5 +++-- drivers/media/v4l2-core/videobuf2-vmalloc.c| 4 ++-- include/media/videobuf2-core.h | 23 +++ 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..22d6105 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); void *mem_priv; int plane; int ret = -ENOMEM; @@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index fb6a177..a44e383 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, buf->dma_dir = dma_dir; offset = vaddr & ~PAGE_MASK; - vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE); + vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir)); if (IS_ERR(vec)) { ret = PTR_ERR(vec); goto fail_buf; diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index ecff8f49..51c98f6 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, buf->offset = vaddr & ~PAGE_MASK; buf->size = size; buf->dma_sgt = >sg_table; - vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE); + vec = vb2_create_framevec(vaddr, size, + VB2_DMA_DIR_CAPTURE(buf->dma_dir)); if (IS_ERR(vec)) goto userptr_fail_pfnvec; buf->vec = vec; @@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv) vm_unmap_ram(buf->vaddr, buf->num_pages); sg_free_table(buf->
[PATCH v2 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks
This patch moves vb2_dc_get_base_sgt() function above mmap buffers callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it will be called for cacheable MMAP support introduced in the next patch. Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index a44e383..0d9665d 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt) return size; } +static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) +{ + int ret; + struct sg_table *sgt; + + sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + dev_err(buf->dev, "failed to alloc sg table\n"); + return NULL; + } + + ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr, + buf->size, buf->attrs); + if (ret < 0) { + dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); + kfree(sgt); + return NULL; + } + + return sgt; +} + /*/ /* callbacks for all buffers */ /*/ @@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = { .release = vb2_dc_dmabuf_ops_release, }; -static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) -{ - int ret; - struct sg_table *sgt; - - sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); - if (!sgt) { - dev_err(buf->dev, "failed to alloc sg table\n"); - return NULL; - } - - ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr, - buf->size, buf->attrs); - if (ret < 0) { - dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); - kfree(sgt); - return NULL; - } - - return sgt; -} - static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags) { struct vb2_dc_buf *buf = buf_priv; -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/2] [media] videobuf2-dc: Support cacheable MMAP
From: Heng-Ruey Hsu <henry...@chromium.org> DMA allocations for MMAP type are uncached by default. But for some cases, CPU has to access the buffers. ie: memcpy for format converter. Supporting cacheable MMAP improves huge performance. This patch enables cacheable memory for DMA coherent allocator in mmap buffer allocation if non-consistent DMA attribute is set and kernel mapping is present. Even if userspace doesn't mmap the buffer, sync still should be happening if kernel mapping is present. If not done in allocation, it is enabled when memory is mapped from userspace when no kernel mapping is present and non-consistent DMA attribute set. Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org> Tested-by: Heng-ruey Hsu <henry...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-dma-contig.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 0d9665d..1f7649d 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv) sg_free_table(buf->sgt_base); kfree(buf->sgt_base); } + if (buf->dma_sgt) { + sg_free_table(buf->dma_sgt); + kfree(buf->dma_sgt); + } dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, buf->attrs); put_device(buf->dev); @@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, buf->handler.put = vb2_dc_put; buf->handler.arg = buf; + /* +* Enable cacheable memory. Even if userspace doesn't mmap the buffer, +* sync still should be happening if kernel mapping is present. +*/ + if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) && + buf->attrs & DMA_ATTR_NON_CONSISTENT) + buf->dma_sgt = vb2_dc_get_base_sgt(buf); + atomic_inc(>refcount); return buf; @@ -227,6 +239,12 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma) vma->vm_ops->open(vma); + /* Enable cacheable memory if not enabled in allocation. */ + if (!buf->dma_sgt && + buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING && + buf->attrs & DMA_ATTR_NON_CONSISTENT) + buf->dma_sgt = vb2_dc_get_base_sgt(buf); + pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n", __func__, (unsigned long)buf->dma_addr, vma->vm_start, buf->size); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/2] [media] videobuf2-dc: Add support for cacheable MMAP
Hi, This series adds support for cacheable MMAP in DMA coherent allocator. The first patch moves the vb2_dc_get_base_sgt() function above mmap callbacks for calls introduced by the second patch. This avoids a forward declaration. Changes in v2: - Put function move in a separate patch - Added comments Heng-Ruey Hsu (1): [media] videobuf2-dc: Support cacheable MMAP Thierry Escande (1): [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks drivers/media/v4l2-core/videobuf2-dma-contig.c | 62 +- 1 file changed, 40 insertions(+), 22 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4] [media] vb2: Add support for capture_dma_bidirectional queue flag
From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues as we don't want to allow HW to be able to write to OUTPUT buffers. This patch introduces 2 macros: VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue type, tanking care of the capture_dma_birectional flag. VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA direction refers to a capture buffer. This test is used to map virtual addresses for writing and to mark pages as dirty. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- Changes since v1: - Renamed use_dma_bidirectional field as capture_dma_bidirectional - Added a VB2_DMA_DIR() macro Changes since v2: - Get rid of dma_dir field and therefore squashed the previous patch Changes since v3: - Fixed typos in include/media/videobuf2-core.h - Added VB2_DMA_DIR_CAPTURE() test macro drivers/media/v4l2-core/videobuf2-core.c | 9 +++-- drivers/media/v4l2-core/videobuf2-dma-contig.c | 2 +- drivers/media/v4l2-core/videobuf2-dma-sg.c | 5 +++-- drivers/media/v4l2-core/videobuf2-vmalloc.c| 4 ++-- include/media/videobuf2-core.h | 24 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..22d6105 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); void *mem_priv; int plane; int ret = -ENOMEM; @@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index fb6a177..a44e383 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, buf->dma_dir = dma_dir; offset = vaddr & ~PAGE_MASK; - vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE); + vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir)); if (IS_ERR(vec)) { ret = PTR_ERR(vec); goto fail_buf; diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index ecff8f49..51c98f6 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, buf->offset = vaddr & ~PAGE_MASK; buf->size = size; buf->dma_sgt = >sg_table; - vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE); + vec = vb2_create_framevec(vaddr, size, + VB2_DMA_DIR_CAPTURE(buf->dma_dir)); if (IS_ERR(vec)) goto userptr_fail_pfnvec; buf->vec = vec; @@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv) vm_unmap_ram(buf->vaddr, buf->num_pages); sg_free_table(buf->dma_sgt); while (--i >= 0) { -
Re: [PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag
Hi Sakari, On 21/10/2016 09:48, Sakari Ailus wrote: Hi Thierry, On Fri, Oct 21, 2016 at 09:25:05AM +0200, Thierry Escande wrote: From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues as we don't want to allow HW to be able to write to OUTPUT buffers. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> Please also check where dma_dir is being used especially in memory type implementation. There are several comparisons to DMA_FROM_DEVICE which will have a different result if DMA_BIDIRECTIONAL is used instead. Nice catch, thanks. How about a macro like this: #define VB2_DMA_DIR_CAPTURE(d) \ ((d) == DMA_FROM_DEVICE || (d) == DMA_BIDIRECTIONAL) Regards, Thierry -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag
From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues as we don't want to allow HW to be able to write to OUTPUT buffers. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- Changes since v1: - Renamed use_dma_bidirectional field as capture_dma_bidirectional - Added a VB2_DMA_DIR() macro Changes since v2: - Get rid of dma_dir field and therefore squashed the previous patch Changes since v3: - Fixed typos in include/media/videobuf2-core.h drivers/media/v4l2-core/videobuf2-core.c | 9 +++-- include/media/videobuf2-core.h | 15 +++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..22d6105 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); void *mem_priv; int plane; int ret = -ENOMEM; @@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index ac5898a..a6cfdfb 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -433,6 +433,9 @@ struct vb2_buf_ops { * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF * has not been called. This is a vb1 idiom that has been adopted * also by vb2. + * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this + * allows HW to read from the CAPTURE buffers in + * addition to writing; ignored for OUTPUT queues. * @lock: pointer to a mutex that protects the vb2_queue struct. The * driver can set this to a mutex to let the v4l2 core serialize * the queuing ioctls. If the driver wants to handle locking @@ -499,6 +502,7 @@ struct vb2_queue { unsignedfileio_write_immediately:1; unsignedallow_zero_bytesused:1; unsigned quirk_poll_must_check_waiting_for_buffers:1; + unsignedcapture_dma_bidirectional:1; struct mutex*lock; void*owner; @@ -554,6 +558,17 @@ struct vb2_queue { #endif }; +/* + * Returns the corresponding DMA direction given the vb2_queue type (capture or + * output). Returns DMA_BIDIRECTIONAL for capture buffers if the vb2_queue field + * capture_dma_bidirectional is set by the driver. + */ +#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type) \ + ? DMA_TO_DEVICE \ + : (q)->capture_dma_bidirectional \ + ? DMA_BIDIRECTIONAL\ + : DMA_FROM_DEVICE) + /** * vb2_plane_vaddr() - Return a kernel virtual address of a given plane * @vb:vb2_buffer to which the plane in question belongs to -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag
From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues as we don't want to allow HW to be able to write to OUTPUT buffers. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- Changes since v1: - Renamed use_dma_bidirectional field as capture_dma_bidirectional - Added a VB2_DMA_DIR() macro Changes since v2: - Get rid of dma_dir field and therefore squashed the previous patch drivers/media/v4l2-core/videobuf2-core.c | 9 +++-- include/media/videobuf2-core.h | 15 +++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..22d6105 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); void *mem_priv; int plane; int ret = -ENOMEM; @@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + enum dma_data_direction dma_dir = VB2_DMA_DIR(q); bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index ac5898a..631f08b 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -433,6 +433,9 @@ struct vb2_buf_ops { * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF * has not been called. This is a vb1 idiom that has been adopted * also by vb2. + * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this + * allows HW to read from the CAPTURE buffers in + * addition to writing; ignored for OUTPUT queues. * @lock: pointer to a mutex that protects the vb2_queue struct. The * driver can set this to a mutex to let the v4l2 core serialize * the queuing ioctls. If the driver wants to handle locking @@ -499,6 +502,7 @@ struct vb2_queue { unsignedfileio_write_immediately:1; unsignedallow_zero_bytesused:1; unsigned quirk_poll_must_check_waiting_for_buffers:1; + unsignedcapture_dma_bidirectional:1; struct mutex*lock; void*owner; @@ -554,6 +558,17 @@ struct vb2_queue { #endif }; +/* + * Return the corresponding DMA direction given the vb2_queue type (capture or + * output). returns DMA_BIRECTIONAL for capture buffers if the vb2_queue field + * capture_dma_bidirectional is set by the driver. + */ +#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type) \ + ? DMA_TO_DEVICE \ + : (q)->capture_dma_bidirectional \ + ? DMA_BIDIRECTIONAL\ + : DMA_FROM_DEVICE) + /** * vb2_plane_vaddr() - Return a kernel virtual address of a given plane * @vb:vb2_buffer to which the plane in question belongs to -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue
Hi Sakari, On 19/10/2016 23:29, Sakari Ailus wrote: Hi Thierry, On Wed, Oct 19, 2016 at 10:24:16AM +0200, Thierry Escande wrote: From: Pawel Osciak <posc...@chromium.org> Store dma_dir in struct vb2_queue and reuse it, instead of recalculating it each time. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Reviewed-by: Owen Lin <owen...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-core.c | 12 +++- drivers/media/v4l2-core/videobuf2-v4l2.c | 2 ++ include/media/videobuf2-core.h | 2 ++ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..f12103c 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; void *mem_priv; int plane; int ret = -ENOMEM; @@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) mem_priv = call_ptr_memop(vb, alloc, q->alloc_devs[plane] ? : q->dev, - q->dma_attrs, size, dma_dir, q->gfp_flags); + q->dma_attrs, size, q->dma_dir, q->gfp_flags); My bad, I guess I expressed myself unclearly. Could you introduce the macro in this patch? You can then remove q->dma_dir altogether. My bad. Sorry for the confusion... The v3 is on its way. Regards, Thierry -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] [media] vb2: Add support for capture_dma_bidirectional queue flag
From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware, which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues, as we don't want to allow HW to be able to write to OUTPUT buffers. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-v4l2.c | 3 +-- include/media/videobuf2-core.h | 14 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index fde1e2d..c92197c 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -659,8 +659,7 @@ int vb2_queue_init(struct vb2_queue *q) * queues will always initialize waiting_for_buffers to false. */ q->quirk_poll_must_check_waiting_for_buffers = true; - q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type) - ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + q->dma_dir = VB2_DMA_DIR(q); return vb2_core_queue_init(q); } diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 38410dd..cd55917 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -433,6 +433,9 @@ struct vb2_buf_ops { * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF * has not been called. This is a vb1 idiom that has been adopted * also by vb2. + * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this + * allows HW to read from the CAPTURE buffers in + * addition to writing; ignored for OUTPUT queues. * @lock: pointer to a mutex that protects the vb2_queue struct. The * driver can set this to a mutex to let the v4l2 core serialize * the queuing ioctls. If the driver wants to handle locking @@ -500,6 +503,7 @@ struct vb2_queue { unsignedfileio_write_immediately:1; unsignedallow_zero_bytesused:1; unsigned quirk_poll_must_check_waiting_for_buffers:1; + unsignedcapture_dma_bidirectional:1; struct mutex*lock; void*owner; @@ -556,6 +560,16 @@ struct vb2_queue { #endif }; +/* + * Return the corresponding DMA direction given the vb2_queue type (capture or + * output). returns DMA_BIRECTIONAL for capture buffers if set by the driver. + */ +#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type) \ + ? DMA_TO_DEVICE \ + : (q)->capture_dma_bidirectional \ + ? DMA_BIDIRECTIONAL\ + : DMA_FROM_DEVICE) + /** * vb2_plane_vaddr() - Return a kernel virtual address of a given plane * @vb:vb2_buffer to which the plane in question belongs to -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue
From: Pawel Osciak <posc...@chromium.org> Store dma_dir in struct vb2_queue and reuse it, instead of recalculating it each time. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Reviewed-by: Owen Lin <owen...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-core.c | 12 +++- drivers/media/v4l2-core/videobuf2-v4l2.c | 2 ++ include/media/videobuf2-core.h | 2 ++ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..f12103c 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; void *mem_priv; int plane; int ret = -ENOMEM; @@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) mem_priv = call_ptr_memop(vb, alloc, q->alloc_devs[plane] ? : q->dev, - q->dma_attrs, size, dma_dir, q->gfp_flags); + q->dma_attrs, size, q->dma_dir, q->gfp_flags); if (IS_ERR(mem_priv)) { if (mem_priv) ret = PTR_ERR(mem_priv); @@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_devs[plane] ? : q->dev, planes[plane].m.userptr, - planes[plane].length, dma_dir); + planes[plane].length, q->dma_dir); if (IS_ERR(mem_priv)) { dprintk(1, "failed acquiring userspace " "memory for plane %d\n", plane); @@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) /* Acquire each plane's memory */ mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_devs[plane] ? : q->dev, - dbuf, planes[plane].length, dma_dir); + dbuf, planes[plane].length, q->dma_dir); if (IS_ERR(mem_priv)) { dprintk(1, "failed to attach dmabuf\n"); ret = PTR_ERR(mem_priv); diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 52ef883..fde1e2d 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q) * queues will always initialize waiting_for_buffers to false. */ q->quirk_poll_must_check_waiting_for_buffers = true; + q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type) + ? DMA_TO_DEVICE : DMA_FROM_DEVICE; return vb2_core_queue_init(q); } diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index ac5898a..38410dd 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -489,6 +489,7 @@ struct vb2_buf_ops { * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued. * @fileio:file io emulator internal data, used only if emulator is active * @threadio: thread io internal data, used only if thread is active + * @dma_dir: DMA direction to use for buffers on this queue */ struct vb2_queue { unsigned inttype; @@ -540,6 +541,7 @@ struct vb2_queue { struct vb2_fileio_data *fileio; struct vb2_threadio_data
[PATCH 0/2] [media] DMA direction support in vb2_queue
Hi, This series adds a dma_dir field to the vb2_queue structure in order to store the DMA direction once for all in vb2_queue_init(); It also adds a new capture_dma_bidirectional flag to the vb2_queue structure allowing the hardware to read from the CAPTURE buffer. This flag is ignored for OUTPUT queues. This is used on ChromeOS by the rockchip-vpu driver. Changes since v1: - Renamed use_dma_bidirectional field as capture_dma_bidirectional - Added a VB2_DMA_DIR() macro Pawel Osciak (2): [media] vb2: Store dma_dir in vb2_queue [media] vb2: Add support for capture_dma_bidirectional queue flag drivers/media/v4l2-core/videobuf2-core.c | 12 +++- drivers/media/v4l2-core/videobuf2-v4l2.c | 6 ++ include/media/videobuf2-core.h | 6 ++ 3 files changed, 15 insertions(+), 9 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag
Hi Sakari, On 17/10/2016 12:06, Sakari Ailus wrote: Hi Thierry, Thanks for the set. A few comments below. On Fri, Oct 14, 2016 at 02:08:14PM +0200, Thierry Escande wrote: From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware, which may be using CAPTURE buffers as reference to decode other buffers. Just out of curiosity --- when do you return these buffers back to the user? Once they're no longer needed as reference frames? Tbh, I don't now. This is used by a rockchip vpu driver not yet upstreamed in the chromeos v4.4 kernel tree. Pawel might answer this question I guess. This flag is ignored for OUTPUT queues, as we don't want to allow HW to be able to write to OUTPUT buffers. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++-- include/media/videobuf2-core.h | 4 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index fde1e2d..9255291 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q) * queues will always initialize waiting_for_buffers to false. */ q->quirk_poll_must_check_waiting_for_buffers = true; - q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type) - ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + + if (V4L2_TYPE_IS_OUTPUT(q->type)) + q->dma_dir = DMA_TO_DEVICE; + else + q->dma_dir = q->use_dma_bidirectional + ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE; return vb2_core_queue_init(q); } diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 38410dd..e613c74 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -433,6 +433,9 @@ struct vb2_buf_ops { * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF * has not been called. This is a vb1 idiom that has been adopted * also by vb2. + * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this + * allows HW to read from the CAPTURE buffers in + * addition to writing; ignored for OUTPUT queues * @lock: pointer to a mutex that protects the vb2_queue struct. The * driver can set this to a mutex to let the v4l2 core serialize * the queuing ioctls. If the driver wants to handle locking @@ -500,6 +503,7 @@ struct vb2_queue { unsignedfileio_write_immediately:1; unsignedallow_zero_bytesused:1; unsigned quirk_poll_must_check_waiting_for_buffers:1; + unsigneduse_dma_bidirectional:1; This field is in the same struct as dma_dir which it directly affects. How about adding a macro instead to give you the queue DMA direction instead? E.g. #define vb2_dma_dir(q) \ (V4L2_TYPE_IS_OUTPUT((q)->type) ? DMA_TO_DEVICE : \ (q)->use_dma_bidirectional ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE) I would call this capture_dma_bidirectional as it only affects capture. Or simply choose DMA_BIDIRECTIONAL whenever the flag is set. Sure. Will do. Regards, Thierry -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [media] videobuf2-dma-contig: Support cacheable MMAP
From: Heng-Ruey Hsu <henry...@chromium.org> DMA allocations for MMAP type are uncached by default. But for some cases, CPU has to access the buffers. ie: memcpy for format converter. Supporting cacheable MMAP improves huge performance. Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org> Tested-by: Heng-ruey Hsu <henry...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-dma-contig.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index fb6a177..c953c24 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -42,6 +42,12 @@ struct vb2_dc_buf { }; /*/ +/* Forward declarations*/ +/*/ + +static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf); + +/*/ /*scatterlist table functions*/ /*/ @@ -129,6 +135,10 @@ static void vb2_dc_put(void *buf_priv) sg_free_table(buf->sgt_base); kfree(buf->sgt_base); } + if (buf->dma_sgt) { + sg_free_table(buf->dma_sgt); + kfree(buf->dma_sgt); + } dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, buf->attrs); put_device(buf->dev); @@ -170,6 +180,10 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, buf->handler.put = vb2_dc_put; buf->handler.arg = buf; + if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) && +(buf->attrs & DMA_ATTR_NON_CONSISTENT)) + buf->dma_sgt = vb2_dc_get_base_sgt(buf); + atomic_inc(>refcount); return buf; @@ -205,6 +219,11 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma) vma->vm_ops->open(vma); + if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) && + (buf->attrs & DMA_ATTR_NON_CONSISTENT) && + !buf->dma_sgt) + buf->dma_sgt = vb2_dc_get_base_sgt(buf); + pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n", __func__, (unsigned long)buf->dma_addr, vma->vm_start, buf->size); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag
From: Pawel Osciak <posc...@chromium.org> When this flag is set for CAPTURE queues by the driver on calling vb2_queue_init(), it forces the buffers on the queue to be allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of DMA_FROM_DEVICE. This allows the device not only to write to the buffers, but also read out from them. This may be useful e.g. for codec hardware, which may be using CAPTURE buffers as reference to decode other buffers. This flag is ignored for OUTPUT queues, as we don't want to allow HW to be able to write to OUTPUT buffers. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++-- include/media/videobuf2-core.h | 4 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index fde1e2d..9255291 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q) * queues will always initialize waiting_for_buffers to false. */ q->quirk_poll_must_check_waiting_for_buffers = true; - q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type) - ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + + if (V4L2_TYPE_IS_OUTPUT(q->type)) + q->dma_dir = DMA_TO_DEVICE; + else + q->dma_dir = q->use_dma_bidirectional + ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE; return vb2_core_queue_init(q); } diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 38410dd..e613c74 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -433,6 +433,9 @@ struct vb2_buf_ops { * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF * has not been called. This is a vb1 idiom that has been adopted * also by vb2. + * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this + * allows HW to read from the CAPTURE buffers in + * addition to writing; ignored for OUTPUT queues * @lock: pointer to a mutex that protects the vb2_queue struct. The * driver can set this to a mutex to let the v4l2 core serialize * the queuing ioctls. If the driver wants to handle locking @@ -500,6 +503,7 @@ struct vb2_queue { unsignedfileio_write_immediately:1; unsignedallow_zero_bytesused:1; unsigned quirk_poll_must_check_waiting_for_buffers:1; + unsigneduse_dma_bidirectional:1; struct mutex*lock; void*owner; -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue
From: Pawel Osciak <posc...@chromium.org> Store dma_dir in struct vb2_queue and reuse it, instead of recalculating it each time. Signed-off-by: Pawel Osciak <posc...@chromium.org> Tested-by: Pawel Osciak <posc...@chromium.org> Reviewed-by: Tomasz Figa <tf...@chromium.org> Reviewed-by: Owen Lin <owen...@chromium.org> Signed-off-by: Thierry Escande <thierry.esca...@collabora.com> --- drivers/media/v4l2-core/videobuf2-core.c | 12 +++- drivers/media/v4l2-core/videobuf2-v4l2.c | 2 ++ include/media/videobuf2-core.h | 2 ++ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 21900202..f12103c 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb); static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; void *mem_priv; int plane; int ret = -ENOMEM; @@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) mem_priv = call_ptr_memop(vb, alloc, q->alloc_devs[plane] ? : q->dev, - q->dma_attrs, size, dma_dir, q->gfp_flags); + q->dma_attrs, size, q->dma_dir, q->gfp_flags); if (IS_ERR(mem_priv)) { if (mem_priv) ret = PTR_ERR(mem_priv); @@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_devs[plane] ? : q->dev, planes[plane].m.userptr, - planes[plane].length, dma_dir); + planes[plane].length, q->dma_dir); if (IS_ERR(mem_priv)) { dprintk(1, "failed acquiring userspace " "memory for plane %d\n", plane); @@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) void *mem_priv; unsigned int plane; int ret = 0; - enum dma_data_direction dma_dir = - q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); @@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) /* Acquire each plane's memory */ mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_devs[plane] ? : q->dev, - dbuf, planes[plane].length, dma_dir); + dbuf, planes[plane].length, q->dma_dir); if (IS_ERR(mem_priv)) { dprintk(1, "failed to attach dmabuf\n"); ret = PTR_ERR(mem_priv); diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 52ef883..fde1e2d 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q) * queues will always initialize waiting_for_buffers to false. */ q->quirk_poll_must_check_waiting_for_buffers = true; + q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type) + ? DMA_TO_DEVICE : DMA_FROM_DEVICE; return vb2_core_queue_init(q); } diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index ac5898a..38410dd 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -489,6 +489,7 @@ struct vb2_buf_ops { * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued. * @fileio:file io emulator internal data, used only if emulator is active * @threadio: thread io internal data, used only if thread is active + * @dma_dir: DMA direction to use for buffers on this queue */ struct vb2_queue { unsigned inttype; @@ -540,6 +541,7 @@ struct vb2_queue { struct vb2_fileio_data *fileio; struct vb2_threadio_data
[PATCH 0/2] [media] DMA direction support in vb2_queue
Hi, This series adds a dma_dir field to the vb2_queue structure in order to store the DMA direction once for all in vb2_queue_init(); It also adds a new use_dma_bidirectional flag to the vb2_queue structure allowing the hardware to read from the CAPTURE buffer. This flag is ignored for OUTPUT queues. This is used on ChromeOS by the rockchip-vpu driver. Pawel Osciak (2): [media] vb2: Store dma_dir in vb2_queue [media] vb2: Add support for use_dma_bidirectional queue flag drivers/media/v4l2-core/videobuf2-core.c | 12 +++- drivers/media/v4l2-core/videobuf2-v4l2.c | 6 ++ include/media/videobuf2-core.h | 6 ++ 3 files changed, 15 insertions(+), 9 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html