All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/29] vivid: add support for 4:2:0 formats
@ 2015-03-09 15:44 Hans Verkuil
  2015-03-09 15:44 ` [PATCH 01/29] vivid: the overlay API wasn't disabled completely for multiplanar Hans Verkuil
                   ` (29 more replies)
  0 siblings, 30 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This patch series adds support for most of the 4:2:0 formats that V4L2 has.
In addition, it fixes various bugs, adds some new features and refactors
the test pattern generation code.

The first 8 patches fix bugs and add support for new red/blue checkerboard
patterns.

Patches 9-19 add 4:2:0 support to the test pattern generator code.

Patches 20-25 refactors the test pattern generation function which become
much, much too large.

Patches 26-28 add vivid driver support for the 4:2:0 formats and the last
patch finally enables support for the new formats.

Besides the new 4:2:0 formats support was also added for PIX_FMT_GREY and
some missing 4:2:2 formats.

Regards,

	Hans

Hans Verkuil (29):
  vivid: the overlay API wasn't disabled completely for multiplanar
  vivid: fix typo in plane size checks
  vivid: wrong top/bottom order for FIELD_ALTERNATE
  vivid: use TPG_MAX_PLANES instead of hardcoding plane-arrays
  vivid: fix test pattern movement for V4L2_FIELD_ALTERNATE
  vivid: add new checkboard patterns
  vivid-tpg: don't add offset when switching to monochrome
  vivid: do not allow video loopback for SEQ_TB/BT
  vivid-tpg: separate planes and buffers
  vivid-tpg: add helper functions for single buffer planar formats
  vivid-tpg: add hor/vert downsampling fields
  vivid-tpg: precalculate downsampled lines
  vivid-tpg: correctly average the two pixels in gen_twopix()
  vivid-tpg: add hor/vert downsampling support to tpg_gen_text
  vivid-tpg: finish hor/vert downsampling support
  vivid-tpg: add support for more planar formats
  vivid-tpg: add support for V4L2_PIX_FMT_GREY
  vivid-tpg: add helper functions to simplify common calculations
  vivid-tpg: add const where appropriate
  vivid-tpg: add a new tpg_draw_params structure
  vivid-tpg: move common parameters to tpg_draw_params
  vivid-tpg: move pattern-related fields to struct tpg_draw_params
  vivid-tpg: move 'extras' parameters to tpg_draw_params
  vivid-tpg: move the 'extras' drawing to a separate function
  vivid-tpg: split off the pattern drawing code.
  vivid: add new format fields
  vivid: add support for single buffer planar formats
  vivid: add downsampling support
  vivid: add the new planar and monochrome formats

 Documentation/video4linux/vivid.txt              |   5 +
 drivers/media/platform/vivid/vivid-core.h        |   8 +-
 drivers/media/platform/vivid/vivid-kthread-cap.c | 125 ++--
 drivers/media/platform/vivid/vivid-tpg.c         | 903 ++++++++++++++++-------
 drivers/media/platform/vivid/vivid-tpg.h         | 103 ++-
 drivers/media/platform/vivid/vivid-vid-cap.c     | 100 ++-
 drivers/media/platform/vivid/vivid-vid-common.c  | 207 +++++-
 drivers/media/platform/vivid/vivid-vid-out.c     |  75 +-
 8 files changed, 1109 insertions(+), 417 deletions(-)

-- 
2.1.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/29] vivid: the overlay API wasn't disabled completely for multiplanar
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 02/29] vivid: fix typo in plane size checks Hans Verkuil
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

If the vivid driver is loaded in multiplanar mode, then the capture overlay
functionality should be disabled. This wasn't fully done, which led to
v4l2-compliance errors.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-vid-cap.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 867a29a..550945a 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -1012,8 +1012,12 @@ int vivid_vid_cap_cropcap(struct file *file, void *priv,
 int vidioc_enum_fmt_vid_overlay(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *f)
 {
+	struct vivid_dev *dev = video_drvdata(file);
 	const struct vivid_fmt *fmt;
 
+	if (dev->multiplanar)
+		return -ENOTTY;
+
 	if (f->index >= ARRAY_SIZE(formats_ovl))
 		return -EINVAL;
 
@@ -1032,6 +1036,9 @@ int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
 	struct v4l2_window *win = &f->fmt.win;
 	unsigned clipcount = win->clipcount;
 
+	if (dev->multiplanar)
+		return -ENOTTY;
+
 	win->w.top = dev->overlay_cap_top;
 	win->w.left = dev->overlay_cap_left;
 	win->w.width = compose->width;
@@ -1063,6 +1070,9 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
 	struct v4l2_window *win = &f->fmt.win;
 	int i, j;
 
+	if (dev->multiplanar)
+		return -ENOTTY;
+
 	win->w.left = clamp_t(int, win->w.left,
 			      -dev->fb_cap.fmt.width, dev->fb_cap.fmt.width);
 	win->w.top = clamp_t(int, win->w.top,
@@ -1150,6 +1160,9 @@ int vivid_vid_cap_overlay(struct file *file, void *fh, unsigned i)
 {
 	struct vivid_dev *dev = video_drvdata(file);
 
+	if (dev->multiplanar)
+		return -ENOTTY;
+
 	if (i && dev->fb_vbase_cap == NULL)
 		return -EINVAL;
 
@@ -1169,6 +1182,9 @@ int vivid_vid_cap_g_fbuf(struct file *file, void *fh,
 {
 	struct vivid_dev *dev = video_drvdata(file);
 
+	if (dev->multiplanar)
+		return -ENOTTY;
+
 	*a = dev->fb_cap;
 	a->capability = V4L2_FBUF_CAP_BITMAP_CLIPPING |
 			V4L2_FBUF_CAP_LIST_CLIPPING;
@@ -1185,6 +1201,9 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
 	struct vivid_dev *dev = video_drvdata(file);
 	const struct vivid_fmt *fmt;
 
+	if (dev->multiplanar)
+		return -ENOTTY;
+
 	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/29] vivid: fix typo in plane size checks
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
  2015-03-09 15:44 ` [PATCH 01/29] vivid: the overlay API wasn't disabled completely for multiplanar Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 03/29] vivid: wrong top/bottom order for FIELD_ALTERNATE Hans Verkuil
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The plane size check was hardcoded to plane 0 instead of using the plane
index.

This failed when using the NV61M format which has a larger plane size for
the second plane compared to the first plane.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-vid-cap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 550945a..49f79a0 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -188,9 +188,9 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
 		size = tpg_g_bytesperline(&dev->tpg, p) * dev->fmt_cap_rect.height +
 			dev->fmt_cap->data_offset[p];
 
-		if (vb2_plane_size(vb, 0) < size) {
+		if (vb2_plane_size(vb, p) < size) {
 			dprintk(dev, 1, "%s data will not fit into plane %u (%lu < %lu)\n",
-					__func__, p, vb2_plane_size(vb, 0), size);
+					__func__, p, vb2_plane_size(vb, p), size);
 			return -EINVAL;
 		}
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/29] vivid: wrong top/bottom order for FIELD_ALTERNATE
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
  2015-03-09 15:44 ` [PATCH 01/29] vivid: the overlay API wasn't disabled completely for multiplanar Hans Verkuil
  2015-03-09 15:44 ` [PATCH 02/29] vivid: fix typo in plane size checks Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 04/29] vivid: use TPG_MAX_PLANES instead of hardcoding plane-arrays Hans Verkuil
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The condition to decide whether the current field is top or bottom
was inverted. Fix this.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-kthread-cap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 39a67cf..9898072 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -427,7 +427,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 		 * standards.
 		 */
 		buf->vb.v4l2_buf.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ?
-			V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+			V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
 		/*
 		 * The sequence counter counts frames, not fields. So divide
 		 * by two.
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/29] vivid: use TPG_MAX_PLANES instead of hardcoding plane-arrays
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (2 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 03/29] vivid: wrong top/bottom order for FIELD_ALTERNATE Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 05/29] vivid: fix test pattern movement for V4L2_FIELD_ALTERNATE Hans Verkuil
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Two arrays of size 'max number of planes' have a hardcoded size instead
of using TPG_MAX_PLANES. Fix that, since TPG_MAX_PLANES will be increased
later on.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-core.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 4b497df..191d9b5 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -84,7 +84,7 @@ struct vivid_fmt {
 	bool	can_do_overlay;
 	u32	alpha_mask;
 	u8	planes;
-	u32	data_offset[2];
+	u32	data_offset[TPG_MAX_PLANES];
 };
 
 extern struct vivid_fmt vivid_formats[];
@@ -332,7 +332,7 @@ struct vivid_dev {
 	u32				ycbcr_enc_out;
 	u32				quantization_out;
 	u32				service_set_out;
-	u32				bytesperline_out[2];
+	u32				bytesperline_out[TPG_MAX_PLANES];
 	unsigned			tv_field_out;
 	unsigned			tv_audio_output;
 	bool				vbi_out_have_wss;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/29] vivid: fix test pattern movement for V4L2_FIELD_ALTERNATE
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (3 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 04/29] vivid: use TPG_MAX_PLANES instead of hardcoding plane-arrays Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 06/29] vivid: add new checkboard patterns Hans Verkuil
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The successive TOP/BOTTOM fields did not move as they should: only
every other field actually changed position.

The cause was that the tpg needs to know if it is dealing with a
FIELD_ALTERNATE case since that requires slightly different handling.

So tell the TPG whether or not the field setting is for the ALTERNATE
case or not.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-kthread-cap.c | 3 ++-
 drivers/media/platform/vivid/vivid-tpg.c         | 4 +++-
 drivers/media/platform/vivid/vivid-tpg.h         | 4 +++-
 drivers/media/platform/vivid/vivid-vid-cap.c     | 5 ++++-
 4 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 9898072..9976d45 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -436,7 +436,8 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 	} else {
 		buf->vb.v4l2_buf.field = dev->field_cap;
 	}
-	tpg_s_field(&dev->tpg, buf->vb.v4l2_buf.field);
+	tpg_s_field(&dev->tpg, buf->vb.v4l2_buf.field,
+		    dev->field_cap == V4L2_FIELD_ALTERNATE);
 	tpg_s_perc_fill_blank(&dev->tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
 
 	vivid_precalc_copy_rects(dev);
diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 34493f4..8fa2150 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1409,7 +1409,9 @@ void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 			linestart_older += line_offset;
 			linestart_newer += line_offset;
 		}
-		if (is_60hz) {
+		if (tpg->field_alternate) {
+			linestart_top = linestart_bottom = linestart_older;
+		} else if (is_60hz) {
 			linestart_top = linestart_newer;
 			linestart_bottom = linestart_older;
 		} else {
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index bd8b1c7..8100425 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -98,6 +98,7 @@ struct tpg_data {
 	/* Scaled output frame size */
 	unsigned			scaled_width;
 	u32				field;
+	bool				field_alternate;
 	/* crop coordinates are frame-based */
 	struct v4l2_rect		crop;
 	/* compose coordinates are format-based */
@@ -348,9 +349,10 @@ static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h)
 	tpg->buf_height = h;
 }
 
-static inline void tpg_s_field(struct tpg_data *tpg, unsigned field)
+static inline void tpg_s_field(struct tpg_data *tpg, unsigned field, bool alternate)
 {
 	tpg->field = field;
+	tpg->field_alternate = alternate;
 }
 
 static inline void tpg_s_perc_fill(struct tpg_data *tpg,
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 49f79a0..d41ac44 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -733,7 +733,10 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
 	if (tpg_g_planes(&dev->tpg) > 1)
 		tpg_s_bytesperline(&dev->tpg, 1, mp->plane_fmt[1].bytesperline);
 	dev->field_cap = mp->field;
-	tpg_s_field(&dev->tpg, dev->field_cap);
+	if (dev->field_cap == V4L2_FIELD_ALTERNATE)
+		tpg_s_field(&dev->tpg, V4L2_FIELD_TOP, true);
+	else
+		tpg_s_field(&dev->tpg, dev->field_cap, false);
 	tpg_s_crop_compose(&dev->tpg, &dev->crop_cap, &dev->compose_cap);
 	tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
 	if (vivid_is_sdtv_cap(dev))
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/29] vivid: add new checkboard patterns
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (4 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 05/29] vivid: fix test pattern movement for V4L2_FIELD_ALTERNATE Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 07/29] vivid-tpg: don't add offset when switching to monochrome Hans Verkuil
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add a 2x2 checker patterns and 1x1 and 2x2 red/blue checker patterns.

Useful for testing 4:2:2 and 4:2:0 formats.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 26 +++++++++++++++++++++++---
 drivers/media/platform/vivid/vivid-tpg.h |  3 +++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 8fa2150..e2af384 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -35,7 +35,10 @@ const char * const tpg_pattern_strings[] = {
 	"100% Green",
 	"100% Blue",
 	"16x16 Checkers",
+	"2x2 Checkers",
 	"1x1 Checkers",
+	"2x2 Red/Green Checkers",
+	"1x1 Red/Green Checkers",
 	"Alternating Hor Lines",
 	"Alternating Vert Lines",
 	"One Pixel Wide Cross",
@@ -744,11 +747,14 @@ static void gen_twopix(struct tpg_data *tpg,
 }
 
 /* Return how many pattern lines are used by the current pattern. */
-static unsigned tpg_get_pat_lines(struct tpg_data *tpg)
+static unsigned tpg_get_pat_lines(const struct tpg_data *tpg)
 {
 	switch (tpg->pattern) {
 	case TPG_PAT_CHECKERS_16X16:
+	case TPG_PAT_CHECKERS_2X2:
 	case TPG_PAT_CHECKERS_1X1:
+	case TPG_PAT_COLOR_CHECKERS_2X2:
+	case TPG_PAT_COLOR_CHECKERS_1X1:
 	case TPG_PAT_ALTERNATING_HLINES:
 	case TPG_PAT_CROSS_1_PIXEL:
 	case TPG_PAT_CROSS_2_PIXELS:
@@ -763,14 +769,18 @@ static unsigned tpg_get_pat_lines(struct tpg_data *tpg)
 }
 
 /* Which pattern line should be used for the given frame line. */
-static unsigned tpg_get_pat_line(struct tpg_data *tpg, unsigned line)
+static unsigned tpg_get_pat_line(const struct tpg_data *tpg, unsigned line)
 {
 	switch (tpg->pattern) {
 	case TPG_PAT_CHECKERS_16X16:
 		return (line >> 4) & 1;
 	case TPG_PAT_CHECKERS_1X1:
+	case TPG_PAT_COLOR_CHECKERS_1X1:
 	case TPG_PAT_ALTERNATING_HLINES:
 		return line & 1;
+	case TPG_PAT_CHECKERS_2X2:
+	case TPG_PAT_COLOR_CHECKERS_2X2:
+		return (line & 2) >> 1;
 	case TPG_PAT_100_COLORSQUARES:
 	case TPG_PAT_100_HCOLORBAR:
 		return (line * 8) / tpg->src_height;
@@ -789,7 +799,8 @@ static unsigned tpg_get_pat_line(struct tpg_data *tpg, unsigned line)
  * Which color should be used for the given pattern line and X coordinate.
  * Note: x is in the range 0 to 2 * tpg->src_width.
  */
-static enum tpg_color tpg_get_color(struct tpg_data *tpg, unsigned pat_line, unsigned x)
+static enum tpg_color tpg_get_color(const struct tpg_data *tpg,
+				    unsigned pat_line, unsigned x)
 {
 	/* Maximum number of bars are TPG_COLOR_MAX - otherwise, the input print code
 	   should be modified */
@@ -836,6 +847,15 @@ static enum tpg_color tpg_get_color(struct tpg_data *tpg, unsigned pat_line, uns
 	case TPG_PAT_CHECKERS_1X1:
 		return ((x & 1) ^ (pat_line & 1)) ?
 			TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
+	case TPG_PAT_COLOR_CHECKERS_1X1:
+		return ((x & 1) ^ (pat_line & 1)) ?
+			TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
+	case TPG_PAT_CHECKERS_2X2:
+		return (((x >> 1) & 1) ^ (pat_line & 1)) ?
+			TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
+	case TPG_PAT_COLOR_CHECKERS_2X2:
+		return (((x >> 1) & 1) ^ (pat_line & 1)) ?
+			TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
 	case TPG_PAT_ALTERNATING_HLINES:
 		return pat_line ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
 	case TPG_PAT_ALTERNATING_VLINES:
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index 8100425..e796a54 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -41,7 +41,10 @@ enum tpg_pattern {
 	TPG_PAT_GREEN,
 	TPG_PAT_BLUE,
 	TPG_PAT_CHECKERS_16X16,
+	TPG_PAT_CHECKERS_2X2,
 	TPG_PAT_CHECKERS_1X1,
+	TPG_PAT_COLOR_CHECKERS_2X2,
+	TPG_PAT_COLOR_CHECKERS_1X1,
 	TPG_PAT_ALTERNATING_HLINES,
 	TPG_PAT_ALTERNATING_VLINES,
 	TPG_PAT_CROSS_1_PIXEL,
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/29] vivid-tpg: don't add offset when switching to monochrome
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (5 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 06/29] vivid: add new checkboard patterns Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 08/29] vivid: do not allow video loopback for SEQ_TB/BT Hans Verkuil
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The grayscale values are still full range sRGB, so don't add the
limited range offset.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index e2af384..c1476a2 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -530,7 +530,7 @@ static void precalculate_color(struct tpg_data *tpg, int k)
 	if (tpg->qual == TPG_QUAL_GRAY) {
 		/* Rec. 709 Luma function */
 		/* (0.2126, 0.7152, 0.0722) * (255 * 256) */
-		r = g = b = ((13879 * r + 46688 * g + 4713 * b) >> 16) + (16 << 4);
+		r = g = b = (13879 * r + 46688 * g + 4713 * b) >> 16;
 	}
 
 	/*
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/29] vivid: do not allow video loopback for SEQ_TB/BT
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (6 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 07/29] vivid-tpg: don't add offset when switching to monochrome Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 09/29] vivid-tpg: separate planes and buffers Hans Verkuil
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Sequential top-bottom/bottom-top fields are not supported as video loopback.
This is too much work to implement for field settings that are rarely used.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/video4linux/vivid.txt             | 5 +++++
 drivers/media/platform/vivid/vivid-vid-common.c | 7 +++++++
 2 files changed, 12 insertions(+)

diff --git a/Documentation/video4linux/vivid.txt b/Documentation/video4linux/vivid.txt
index 6cfc854..cd4b5a1 100644
--- a/Documentation/video4linux/vivid.txt
+++ b/Documentation/video4linux/vivid.txt
@@ -912,6 +912,11 @@ looped to the video input provided that:
   sequence and field counting in struct v4l2_buffer on the capture side may not
   be 100% accurate.
 
+- field settings V4L2_FIELD_SEQ_TB/BT are not supported. While it is possible to
+  implement this, it would mean a lot of work to get this right. Since these
+  field values are rarely used the decision was made not to implement this for
+  now.
+
 - on the input side the "Standard Signal Mode" for the S-Video input or the
   "DV Timings Signal Mode" for the HDMI input should be configured so that a
   valid signal is passed to the video input.
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 6bef1e6..49c9bc6 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -210,6 +210,13 @@ bool vivid_vid_can_loop(struct vivid_dev *dev)
 		return false;
 	if (dev->field_cap != dev->field_out)
 		return false;
+	/*
+	 * While this can be supported, it is just too much work
+	 * to actually implement.
+	 */
+	if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
+	    dev->field_cap == V4L2_FIELD_SEQ_BT)
+		return false;
 	if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
 		if (!(dev->std_cap & V4L2_STD_525_60) !=
 		    !(dev->std_out & V4L2_STD_525_60))
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/29] vivid-tpg: separate planes and buffers
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (7 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 08/29] vivid: do not allow video loopback for SEQ_TB/BT Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 10/29] vivid-tpg: add helper functions for single buffer planar formats Hans Verkuil
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add a new field that contains the number of buffers. This may be
less than the number of planes in case multiple planes are combined
into one buffer.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 3 +++
 drivers/media/platform/vivid/vivid-tpg.h | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index c1476a2..7463f78 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -170,7 +170,9 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 {
 	tpg->fourcc = fourcc;
 	tpg->planes = 1;
+	tpg->buffers = 1;
 	tpg->recalc_colors = true;
+
 	switch (fourcc) {
 	case V4L2_PIX_FMT_RGB565:
 	case V4L2_PIX_FMT_RGB565X:
@@ -190,6 +192,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 		break;
 	case V4L2_PIX_FMT_NV16M:
 	case V4L2_PIX_FMT_NV61M:
+		tpg->buffers = 2;
 		tpg->planes = 2;
 		/* fall-through */
 	case V4L2_PIX_FMT_YUYV:
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index e796a54..9ce2d01 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -138,6 +138,7 @@ struct tpg_data {
 	enum tpg_pixel_aspect		pix_aspect;
 	unsigned			rgb_range;
 	unsigned			real_rgb_range;
+	unsigned			buffers;
 	unsigned			planes;
 	/* Used to store the colors in native format, either RGB or YUV */
 	u8				colors[TPG_COLOR_MAX][3];
@@ -327,6 +328,11 @@ static inline u32 tpg_g_quantization(const struct tpg_data *tpg)
 	return tpg->quantization;
 }
 
+static inline unsigned tpg_g_buffers(const struct tpg_data *tpg)
+{
+	return tpg->buffers;
+}
+
 static inline unsigned tpg_g_planes(const struct tpg_data *tpg)
 {
 	return tpg->planes;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/29] vivid-tpg: add helper functions for single buffer planar formats
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (8 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 09/29] vivid-tpg: separate planes and buffers Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 11/29] vivid-tpg: add hor/vert downsampling fields Hans Verkuil
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add helpers functions to determine the line widths and image sizes
for planar formats that are stores in a single buffer.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 18 ++++++++++-
 drivers/media/platform/vivid/vivid-tpg.h | 53 +++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 7463f78..767879e0 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1317,7 +1317,7 @@ void tpg_calc_text_basep(struct tpg_data *tpg,
 		basep[p][0] += tpg->buf_height * stride / 2;
 }
 
-void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
+void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 {
 	bool is_tv = std;
 	bool is_60hz = is_tv && (std & V4L2_STD_525_60);
@@ -1577,3 +1577,19 @@ void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 		}
 	}
 }
+
+void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
+{
+	unsigned offset = 0;
+	unsigned i;
+
+	if (tpg->buffers > 1) {
+		tpg_fill_plane_buffer(tpg, std, p, vbuf);
+		return;
+	}
+
+	for (i = 0; i < tpg->planes; i++) {
+		tpg_fill_plane_buffer(tpg, std, i, vbuf + offset);
+		offset += tpg_calc_plane_size(tpg, i);
+	}
+}
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index 9ce2d01..b90ce7d 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -189,6 +189,7 @@ void tpg_gen_text(struct tpg_data *tpg,
 		u8 *basep[TPG_MAX_PLANES][2], int y, int x, char *text);
 void tpg_calc_text_basep(struct tpg_data *tpg,
 		u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf);
+void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf);
 void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf);
 bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc);
 void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
@@ -350,7 +351,57 @@ static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned p
 
 static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsigned bpl)
 {
-	tpg->bytesperline[plane] = bpl;
+	unsigned p;
+
+	if (tpg->buffers > 1) {
+		tpg->bytesperline[plane] = bpl;
+		return;
+	}
+
+	for (p = 0; p < tpg->planes; p++) {
+		unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
+
+		tpg->bytesperline[p] = plane_w;
+	}
+}
+
+static inline unsigned tpg_g_line_width(const struct tpg_data *tpg, unsigned plane)
+{
+	unsigned w = 0;
+	unsigned p;
+
+	if (tpg->buffers > 1)
+		return tpg_g_bytesperline(tpg, plane);
+	for (p = 0; p < tpg->planes; p++) {
+		unsigned plane_w = tpg_g_bytesperline(tpg, p);
+
+		w += plane_w;
+	}
+	return w;
+}
+
+static inline unsigned tpg_calc_line_width(const struct tpg_data *tpg,
+					   unsigned plane, unsigned bpl)
+{
+	unsigned w = 0;
+	unsigned p;
+
+	if (tpg->buffers > 1)
+		return bpl;
+	for (p = 0; p < tpg->planes; p++) {
+		unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
+
+		w += plane_w;
+	}
+	return w;
+}
+
+static inline unsigned tpg_calc_plane_size(const struct tpg_data *tpg, unsigned plane)
+{
+	if (plane >= tpg->planes)
+		return 0;
+
+	return tpg_g_bytesperline(tpg, plane) * tpg->buf_height;
 }
 
 static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/29] vivid-tpg: add hor/vert downsampling fields
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (9 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 10/29] vivid-tpg: add helper functions for single buffer planar formats Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 12/29] vivid-tpg: precalculate downsampled lines Hans Verkuil
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This is step one of supporting horizontal and vertical downsampling.
This just adds support for the h/vdownsampling fields and it increases
the maximum number of planes to 3.

Currently none of the planar formats need horizontal or vertical
downsampling, so this change has no effect at the moment.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c |  7 ++++++-
 drivers/media/platform/vivid/vivid-tpg.h | 15 ++++++++++-----
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 767879e0..9f47387 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -172,6 +172,8 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	tpg->planes = 1;
 	tpg->buffers = 1;
 	tpg->recalc_colors = true;
+	tpg->vdownsampling[0] = 1;
+	tpg->hdownsampling[0] = 1;
 
 	switch (fourcc) {
 	case V4L2_PIX_FMT_RGB565:
@@ -192,6 +194,8 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 		break;
 	case V4L2_PIX_FMT_NV16M:
 	case V4L2_PIX_FMT_NV61M:
+		tpg->vdownsampling[1] = 1;
+		tpg->hdownsampling[1] = 1;
 		tpg->buffers = 2;
 		tpg->planes = 2;
 		/* fall-through */
@@ -273,7 +277,8 @@ void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
 	tpg->compose.width = width;
 	tpg->compose.height = tpg->buf_height;
 	for (p = 0; p < tpg->planes; p++)
-		tpg->bytesperline[p] = width * tpg->twopixelsize[p] / 2;
+		tpg->bytesperline[p] = (width * tpg->twopixelsize[p]) /
+				       (2 * tpg->hdownsampling[p]);
 	tpg->recalc_square_border = true;
 }
 
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index b90ce7d..cec5bb4 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -90,7 +90,7 @@ enum tpg_move_mode {
 
 extern const char * const tpg_aspect_strings[];
 
-#define TPG_MAX_PLANES 2
+#define TPG_MAX_PLANES 3
 #define TPG_MAX_PAT_LINES 8
 
 struct tpg_data {
@@ -140,6 +140,8 @@ struct tpg_data {
 	unsigned			real_rgb_range;
 	unsigned			buffers;
 	unsigned			planes;
+	u8				vdownsampling[TPG_MAX_PLANES];
+	u8				hdownsampling[TPG_MAX_PLANES];
 	/* Used to store the colors in native format, either RGB or YUV */
 	u8				colors[TPG_COLOR_MAX][3];
 	u8				textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8];
@@ -361,10 +363,11 @@ static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsi
 	for (p = 0; p < tpg->planes; p++) {
 		unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
 
-		tpg->bytesperline[p] = plane_w;
+		tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p];
 	}
 }
 
+
 static inline unsigned tpg_g_line_width(const struct tpg_data *tpg, unsigned plane)
 {
 	unsigned w = 0;
@@ -375,7 +378,7 @@ static inline unsigned tpg_g_line_width(const struct tpg_data *tpg, unsigned pla
 	for (p = 0; p < tpg->planes; p++) {
 		unsigned plane_w = tpg_g_bytesperline(tpg, p);
 
-		w += plane_w;
+		w += plane_w / tpg->vdownsampling[p];
 	}
 	return w;
 }
@@ -391,7 +394,8 @@ static inline unsigned tpg_calc_line_width(const struct tpg_data *tpg,
 	for (p = 0; p < tpg->planes; p++) {
 		unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
 
-		w += plane_w;
+		plane_w /= tpg->hdownsampling[p];
+		w += plane_w / tpg->vdownsampling[p];
 	}
 	return w;
 }
@@ -401,7 +405,8 @@ static inline unsigned tpg_calc_plane_size(const struct tpg_data *tpg, unsigned
 	if (plane >= tpg->planes)
 		return 0;
 
-	return tpg_g_bytesperline(tpg, plane) * tpg->buf_height;
+	return tpg_g_bytesperline(tpg, plane) * tpg->buf_height /
+	       tpg->vdownsampling[plane];
 }
 
 static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/29] vivid-tpg: precalculate downsampled lines
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (10 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 11/29] vivid-tpg: add hor/vert downsampling fields Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 13/29] vivid-tpg: correctly average the two pixels in gen_twopix() Hans Verkuil
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

When dealing with vertical downsampling two successive lines have to be
averaged. In the case of the test pattern generator that only happens
if the two lines are using different patterns. So precalculate the average
between two pattern lines: one of pattern P and one of pattern P + 1.

That way there is no need to do any on-the-fly downsampling: it's all done
in the precalculate phase.

This patch also implements horizontal downsampling in the precalculate phase.
The only thing that needs to be done is to half the width since the actual
downsampling happens when two pixels at a time are generated.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 40 ++++++++++++++++++++++++++++++--
 drivers/media/platform/vivid/vivid-tpg.h |  1 +
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 9f47387..d7531d3 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -128,6 +128,11 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
 			tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
 			if (!tpg->lines[pat][plane])
 				return -ENOMEM;
+			if (plane == 0)
+				continue;
+			tpg->downsampled_lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
+			if (!tpg->downsampled_lines[pat][plane])
+				return -ENOMEM;
 		}
 	}
 	for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
@@ -155,6 +160,10 @@ void tpg_free(struct tpg_data *tpg)
 		for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
 			vfree(tpg->lines[pat][plane]);
 			tpg->lines[pat][plane] = NULL;
+			if (plane == 0)
+				continue;
+			vfree(tpg->downsampled_lines[pat][plane]);
+			tpg->downsampled_lines[pat][plane] = NULL;
 		}
 	for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
 		vfree(tpg->contrast_line[plane]);
@@ -1029,12 +1038,39 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
 			gen_twopix(tpg, pix, tpg->hflip ? color1 : color2, 1);
 			for (p = 0; p < tpg->planes; p++) {
 				unsigned twopixsize = tpg->twopixelsize[p];
-				u8 *pos = tpg->lines[pat][p] + x * twopixsize / 2;
+				unsigned hdiv = tpg->hdownsampling[p];
+				u8 *pos = tpg->lines[pat][p] +
+						(x / hdiv) * twopixsize / 2;
+
+				memcpy(pos, pix[p], twopixsize / hdiv);
+			}
+		}
+	}
+
+	if (tpg->vdownsampling[tpg->planes - 1] > 1) {
+		unsigned pat_lines = tpg_get_pat_lines(tpg);
+
+		for (pat = 0; pat < pat_lines; pat++) {
+			unsigned next_pat = (pat + 1) % pat_lines;
+
+			for (p = 1; p < tpg->planes; p++) {
+				unsigned twopixsize = tpg->twopixelsize[p];
+				unsigned hdiv = tpg->hdownsampling[p];
 
-				memcpy(pos, pix[p], twopixsize);
+				for (x = 0; x < tpg->scaled_width * 2; x += 2) {
+					unsigned offset = (x / hdiv) * twopixsize / 2;
+					u8 *pos1 = tpg->lines[pat][p] + offset;
+					u8 *pos2 = tpg->lines[next_pat][p] + offset;
+					u8 *dest = tpg->downsampled_lines[pat][p] + offset;
+					unsigned i;
+
+					for (i = 0; i < twopixsize / hdiv; i++, dest++, pos1++, pos2++)
+						*dest = ((u16)*pos1 + (u16)*pos2) / 2;
+				}
 			}
 		}
 	}
+
 	for (x = 0; x < tpg->scaled_width; x += 2) {
 		u8 pix[TPG_MAX_PLANES][8];
 
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index cec5bb4..5a53eb9 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -175,6 +175,7 @@ struct tpg_data {
 	/* Used to store TPG_MAX_PAT_LINES lines, each with up to two planes */
 	unsigned			max_line_width;
 	u8				*lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
+	u8				*downsampled_lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
 	u8				*random_line[TPG_MAX_PLANES];
 	u8				*contrast_line[TPG_MAX_PLANES];
 	u8				*black_line[TPG_MAX_PLANES];
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/29] vivid-tpg: correctly average the two pixels in gen_twopix()
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (11 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 12/29] vivid-tpg: precalculate downsampled lines Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 14/29] vivid-tpg: add hor/vert downsampling support to tpg_gen_text Hans Verkuil
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

gen_twopix() is always called twice: once for the first and once for
the second pixel. Improve the code to properly average the two if the
format requires horizontal downsampling.

This is necessary for patterns like 1x1 red/blue checkers.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 48 ++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index d7531d3..9001b9a 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -687,28 +687,64 @@ static void gen_twopix(struct tpg_data *tpg,
 	switch (tpg->fourcc) {
 	case V4L2_PIX_FMT_NV16M:
 		buf[0][offset] = r_y;
-		buf[1][offset] = odd ? b_v : g_u;
+		if (odd) {
+			buf[1][0] = (buf[1][0] + g_u) / 2;
+			buf[1][1] = (buf[1][1] + b_v) / 2;
+			break;
+		}
+		buf[1][0] = g_u;
+		buf[1][1] = b_v;
 		break;
 	case V4L2_PIX_FMT_NV61M:
 		buf[0][offset] = r_y;
-		buf[1][offset] = odd ? g_u : b_v;
+		if (odd) {
+			buf[1][0] = (buf[1][0] + b_v) / 2;
+			buf[1][1] = (buf[1][1] + g_u) / 2;
+			break;
+		}
+		buf[1][0] = b_v;
+		buf[1][1] = g_u;
 		break;
 
 	case V4L2_PIX_FMT_YUYV:
 		buf[0][offset] = r_y;
-		buf[0][offset + 1] = odd ? b_v : g_u;
+		if (odd) {
+			buf[0][1] = (buf[0][1] + g_u) / 2;
+			buf[0][3] = (buf[0][3] + b_v) / 2;
+			break;
+		}
+		buf[0][1] = g_u;
+		buf[0][3] = b_v;
 		break;
 	case V4L2_PIX_FMT_UYVY:
-		buf[0][offset] = odd ? b_v : g_u;
 		buf[0][offset + 1] = r_y;
+		if (odd) {
+			buf[0][0] = (buf[0][0] + g_u) / 2;
+			buf[0][2] = (buf[0][2] + b_v) / 2;
+			break;
+		}
+		buf[0][0] = g_u;
+		buf[0][2] = b_v;
 		break;
 	case V4L2_PIX_FMT_YVYU:
 		buf[0][offset] = r_y;
-		buf[0][offset + 1] = odd ? g_u : b_v;
+		if (odd) {
+			buf[0][1] = (buf[0][1] + b_v) / 2;
+			buf[0][3] = (buf[0][3] + g_u) / 2;
+			break;
+		}
+		buf[0][1] = b_v;
+		buf[0][3] = g_u;
 		break;
 	case V4L2_PIX_FMT_VYUY:
-		buf[0][offset] = odd ? g_u : b_v;
 		buf[0][offset + 1] = r_y;
+		if (odd) {
+			buf[0][0] = (buf[0][0] + b_v) / 2;
+			buf[0][2] = (buf[0][2] + g_u) / 2;
+			break;
+		}
+		buf[0][0] = b_v;
+		buf[0][2] = g_u;
 		break;
 	case V4L2_PIX_FMT_RGB565:
 		buf[0][offset] = (g_u << 5) | b_v;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/29] vivid-tpg: add hor/vert downsampling support to tpg_gen_text
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (12 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 13/29] vivid-tpg: correctly average the two pixels in gen_twopix() Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 15/29] vivid-tpg: finish hor/vert downsampling support Hans Verkuil
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This will just skip lines/pixels since color fidelity is not quite
as important here as it is with the test patterns themselves.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 9001b9a..f03289f 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1183,24 +1183,37 @@ void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
 		div = 2;
 
 	for (p = 0; p < tpg->planes; p++) {
-		/* Print stream time */
+		unsigned vdiv = tpg->vdownsampling[p];
+		unsigned hdiv = tpg->hdownsampling[p];
+
+		/* Print text */
 #define PRINTSTR(PIXTYPE) do {	\
 	PIXTYPE fg;	\
 	PIXTYPE bg;	\
 	memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE));	\
 	memcpy(&bg, tpg->textbg[p], sizeof(PIXTYPE));	\
 	\
-	for (line = first; line < 16; line += step) {	\
+	for (line = first; line < 16; line += vdiv * step) {	\
 		int l = tpg->vflip ? 15 - line : line; \
-		PIXTYPE *pos = (PIXTYPE *)(basep[p][line & 1] + \
-			       ((y * step + l) / div) * tpg->bytesperline[p] + \
-			       x * sizeof(PIXTYPE));	\
+		PIXTYPE *pos = (PIXTYPE *)(basep[p][(line / vdiv) & 1] + \
+			       ((y * step + l) / (vdiv * div)) * tpg->bytesperline[p] + \
+			       (x / hdiv) * sizeof(PIXTYPE));	\
 		unsigned s;	\
 	\
 		for (s = 0; s < len; s++) {	\
 			u8 chr = font8x16[text[s] * 16 + line];	\
 	\
-			if (tpg->hflip) { \
+			if (hdiv == 2 && tpg->hflip) { \
+				pos[3] = (chr & (0x01 << 6) ? fg : bg);	\
+				pos[2] = (chr & (0x01 << 4) ? fg : bg);	\
+				pos[1] = (chr & (0x01 << 2) ? fg : bg);	\
+				pos[0] = (chr & (0x01 << 0) ? fg : bg);	\
+			} else if (hdiv == 2) { \
+				pos[0] = (chr & (0x01 << 7) ? fg : bg);	\
+				pos[1] = (chr & (0x01 << 5) ? fg : bg);	\
+				pos[2] = (chr & (0x01 << 3) ? fg : bg);	\
+				pos[3] = (chr & (0x01 << 1) ? fg : bg);	\
+			} else if (tpg->hflip) { \
 				pos[7] = (chr & (0x01 << 7) ? fg : bg);	\
 				pos[6] = (chr & (0x01 << 6) ? fg : bg);	\
 				pos[5] = (chr & (0x01 << 5) ? fg : bg);	\
@@ -1220,7 +1233,7 @@ void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
 				pos[7] = (chr & (0x01 << 0) ? fg : bg);	\
 			} \
 	\
-			pos += tpg->hflip ? -8 : 8;	\
+			pos += (tpg->hflip ? -8 : 8) / hdiv;	\
 		}	\
 	}	\
 } while (0)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/29] vivid-tpg: finish hor/vert downsampling support
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (13 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 14/29] vivid-tpg: add hor/vert downsampling support to tpg_gen_text Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 16/29] vivid-tpg: add support for more planar formats Hans Verkuil
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Implement horizontal and vertical downsampling when filling in the
plane. The TPG is now ready to support such formats.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 128 ++++++++++++++++++++++++++-----
 1 file changed, 110 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index f03289f..7d8e87e 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1396,15 +1396,29 @@ void tpg_calc_text_basep(struct tpg_data *tpg,
 		u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf)
 {
 	unsigned stride = tpg->bytesperline[p];
+	unsigned h = tpg->buf_height;
 
 	tpg_recalc(tpg);
 
 	basep[p][0] = vbuf;
 	basep[p][1] = vbuf;
+	h /= tpg->vdownsampling[p];
 	if (tpg->field == V4L2_FIELD_SEQ_TB)
-		basep[p][1] += tpg->buf_height * stride / 2;
+		basep[p][1] += h * stride / 2;
 	else if (tpg->field == V4L2_FIELD_SEQ_BT)
-		basep[p][0] += tpg->buf_height * stride / 2;
+		basep[p][0] += h * stride / 2;
+}
+
+static int tpg_pattern_avg(const struct tpg_data *tpg,
+			   unsigned pat1, unsigned pat2)
+{
+	unsigned pat_lines = tpg_get_pat_lines(tpg);
+
+	if (pat1 == (pat2 + 1) % pat_lines)
+		return pat2;
+	if (pat2 == (pat1 + 1) % pat_lines)
+		return pat1;
+	return -1;
 }
 
 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
@@ -1420,7 +1434,9 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	int hmax = (tpg->compose.height * tpg->perc_fill) / 100;
 	int h;
 	unsigned twopixsize = tpg->twopixelsize[p];
-	unsigned img_width = tpg->compose.width * twopixsize / 2;
+	unsigned hdiv = tpg->hdownsampling[p];
+	unsigned vdiv = tpg->vdownsampling[p];
+	unsigned img_width = (tpg->compose.width / hdiv) * twopixsize / 2;
 	unsigned line_offset;
 	unsigned left_pillar_width = 0;
 	unsigned right_pillar_start = img_width;
@@ -1446,18 +1462,18 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 
 	vbuf += tpg->compose.left * twopixsize / 2;
 	line_offset = tpg->crop.left * tpg->scaled_width / tpg->src_width;
-	line_offset = (line_offset & ~1) * twopixsize / 2;
+	line_offset = ((line_offset & ~1) / hdiv) * twopixsize / 2;
 	if (tpg->crop.left < tpg->border.left) {
 		left_pillar_width = tpg->border.left - tpg->crop.left;
 		if (left_pillar_width > tpg->crop.width)
 			left_pillar_width = tpg->crop.width;
 		left_pillar_width = (left_pillar_width * tpg->scaled_width) / tpg->src_width;
-		left_pillar_width = (left_pillar_width & ~1) * twopixsize / 2;
+		left_pillar_width = ((left_pillar_width & ~1) / hdiv) * twopixsize / 2;
 	}
 	if (tpg->crop.left + tpg->crop.width > tpg->border.left + tpg->border.width) {
 		right_pillar_start = tpg->border.left + tpg->border.width - tpg->crop.left;
 		right_pillar_start = (right_pillar_start * tpg->scaled_width) / tpg->src_width;
-		right_pillar_start = (right_pillar_start & ~1) * twopixsize / 2;
+		right_pillar_start = ((right_pillar_start & ~1) / hdiv) * twopixsize / 2;
 		if (right_pillar_start > img_width)
 			right_pillar_start = img_width;
 	}
@@ -1486,6 +1502,26 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			src_y++;
 		}
 
+		if (vdiv > 1) {
+			/*
+			 * When doing vertical downsampling the field setting
+			 * matters: for SEQ_BT/TB we downsample each field
+			 * separately (i.e. lines 0+2 are combined, as are
+			 * lines 1+3), for the other field settings we combine
+			 * odd and even lines. Doing that for SEQ_BT/TB would
+			 * be really weird.
+			 */
+			if (tpg->field == V4L2_FIELD_SEQ_BT ||
+			    tpg->field == V4L2_FIELD_SEQ_TB) {
+				if ((h & 3) >= 2)
+					continue;
+			} else if (h & 1) {
+				continue;
+			}
+
+			buf_line /= vdiv;
+		}
+
 		if (h >= hmax) {
 			if (hmax == tpg->compose.height)
 				continue;
@@ -1511,14 +1547,63 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			linestart_newer = tpg->random_line[p] +
 					  twopixsize * prandom_u32_max(tpg->src_width / 2);
 		} else {
-			pat_line_old = tpg_get_pat_line(tpg,
-						(frame_line + mv_vert_old) % tpg->src_height);
-			pat_line_new = tpg_get_pat_line(tpg,
-						(frame_line + mv_vert_new) % tpg->src_height);
+			unsigned frame_line_old =
+				(frame_line + mv_vert_old) % tpg->src_height;
+			unsigned frame_line_new =
+				(frame_line + mv_vert_new) % tpg->src_height;
+			unsigned pat_line_next_old;
+			unsigned pat_line_next_new;
+
+			pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
+			pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
 			linestart_older = tpg->lines[pat_line_old][p] +
-					  mv_hor_old * twopixsize / 2;
+				(mv_hor_old / hdiv) * twopixsize / 2;
 			linestart_newer = tpg->lines[pat_line_new][p] +
-					  mv_hor_new * twopixsize / 2;
+				(mv_hor_new / hdiv) * twopixsize / 2;
+
+			if (vdiv > 1) {
+				unsigned frame_line_next;
+				int avg_pat;
+
+				/*
+				 * Now decide whether we need to use downsampled_lines[].
+				 * That's necessary if the two lines use different patterns.
+				 */
+				frame_line_next = tpg_calc_frameline(tpg, src_y, tpg->field);
+				if (tpg->vflip)
+					frame_line_next = tpg->src_height - frame_line_next - 1;
+				pat_line_next_old = tpg_get_pat_line(tpg,
+						(frame_line_next + mv_vert_old) % tpg->src_height);
+				pat_line_next_new = tpg_get_pat_line(tpg,
+						(frame_line_next + mv_vert_new) % tpg->src_height);
+
+				switch (tpg->field) {
+				case V4L2_FIELD_INTERLACED:
+				case V4L2_FIELD_INTERLACED_BT:
+				case V4L2_FIELD_INTERLACED_TB:
+					avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
+					if (avg_pat < 0)
+						break;
+					linestart_older = tpg->downsampled_lines[avg_pat][p] +
+						(mv_hor_old / hdiv) * twopixsize / 2;
+					linestart_newer = linestart_older;
+					break;
+				case V4L2_FIELD_NONE:
+				case V4L2_FIELD_TOP:
+				case V4L2_FIELD_BOTTOM:
+				case V4L2_FIELD_SEQ_BT:
+				case V4L2_FIELD_SEQ_TB:
+					avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
+					if (avg_pat >= 0)
+						linestart_older = tpg->downsampled_lines[avg_pat][p] +
+							(mv_hor_old / hdiv) * twopixsize / 2;
+					avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
+					if (avg_pat >= 0)
+						linestart_newer = tpg->downsampled_lines[avg_pat][p] +
+							(mv_hor_new / hdiv) * twopixsize / 2;
+					break;
+				}
+			}
 			linestart_older += line_offset;
 			linestart_newer += line_offset;
 		}
@@ -1568,12 +1653,13 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			u8 *wss = tpg->random_line[p] +
 				  twopixsize * prandom_u32_max(tpg->src_width / 2);
 
-			memcpy(vbuf + buf_line * stride, wss, wss_width * twopixsize / 2);
+			memcpy(vbuf + buf_line * stride, wss,
+			       (wss_width / hdiv) * twopixsize / 2);
 		}
 	}
 
 	vbuf = orig_vbuf;
-	vbuf += tpg->compose.left * twopixsize / 2;
+	vbuf += (tpg->compose.left / hdiv) * twopixsize / 2;
 	src_y = 0;
 	error = 0;
 	for (h = 0; h < tpg->compose.height; h++) {
@@ -1590,6 +1676,12 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			src_y++;
 		}
 
+		if (vdiv > 1) {
+			if (h & 1)
+				continue;
+			buf_line /= vdiv;
+		}
+
 		if (tpg->show_border && frame_line >= b->top &&
 		    frame_line < b->top + b->height) {
 			unsigned bottom = b->top + b->height - 1;
@@ -1632,13 +1724,13 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 				width -= left + width - c->left - c->width;
 			left -= c->left;
 			left = (left * tpg->scaled_width) / tpg->src_width;
-			left = (left & ~1) * twopixsize / 2;
+			left = ((left & ~1) / hdiv) * twopixsize / 2;
 			width = (width * tpg->scaled_width) / tpg->src_width;
-			width = (width & ~1) * twopixsize / 2;
+			width = ((width & ~1) / hdiv) * twopixsize / 2;
 			memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], width);
 		}
 		if (tpg->insert_sav) {
-			unsigned offset = (tpg->compose.width / 6) * twopixsize;
+			unsigned offset = (tpg->compose.width / (6 * hdiv)) * twopixsize;
 			u8 *p = vbuf + buf_line * stride + offset;
 			unsigned vact = 0, hact = 0;
 
@@ -1652,7 +1744,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 				(hact ^ vact ^ f);
 		}
 		if (tpg->insert_eav) {
-			unsigned offset = (tpg->compose.width / 6) * 2 * twopixsize;
+			unsigned offset = (tpg->compose.width / (6 * hdiv)) * 2 * twopixsize;
 			u8 *p = vbuf + buf_line * stride + offset;
 			unsigned vact = 0, hact = 1;
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 16/29] vivid-tpg: add support for more planar formats
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (14 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 15/29] vivid-tpg: finish hor/vert downsampling support Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 17/29] vivid-tpg: add support for V4L2_PIX_FMT_GREY Hans Verkuil
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Now that the support for hor/vert downsampled planar formats is in
place we can add support for such formats to the TPG.

This patch adds support for:

V4L2_PIX_FMT_YUV420M
V4L2_PIX_FMT_YVU420M
V4L2_PIX_FMT_YUV420
V4L2_PIX_FMT_YVU420
V4L2_PIX_FMT_YUV422P
V4L2_PIX_FMT_NV16
V4L2_PIX_FMT_NV61
V4L2_PIX_FMT_NV12
V4L2_PIX_FMT_NV21
V4L2_PIX_FMT_NV12P
V4L2_PIX_FMT_NV21P

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 90 +++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 7d8e87e..19b5806 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -201,13 +201,49 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_ABGR32:
 		tpg->is_yuv = false;
 		break;
+	case V4L2_PIX_FMT_YUV420M:
+	case V4L2_PIX_FMT_YVU420M:
+		tpg->buffers = 3;
+		/* fall through */
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		tpg->vdownsampling[1] = 2;
+		tpg->vdownsampling[2] = 2;
+		tpg->hdownsampling[1] = 2;
+		tpg->hdownsampling[2] = 2;
+		tpg->planes = 3;
+		tpg->is_yuv = true;
+		break;
+	case V4L2_PIX_FMT_YUV422P:
+		tpg->vdownsampling[1] = 1;
+		tpg->vdownsampling[2] = 1;
+		tpg->hdownsampling[1] = 2;
+		tpg->hdownsampling[2] = 2;
+		tpg->planes = 3;
+		tpg->is_yuv = true;
+		break;
 	case V4L2_PIX_FMT_NV16M:
 	case V4L2_PIX_FMT_NV61M:
+		tpg->buffers = 2;
+		/* fall through */
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV61:
 		tpg->vdownsampling[1] = 1;
 		tpg->hdownsampling[1] = 1;
+		tpg->planes = 2;
+		tpg->is_yuv = true;
+		break;
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV21M:
 		tpg->buffers = 2;
+		/* fall through */
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		tpg->vdownsampling[1] = 2;
+		tpg->hdownsampling[1] = 1;
 		tpg->planes = 2;
-		/* fall-through */
+		tpg->is_yuv = true;
+		break;
 	case V4L2_PIX_FMT_YUYV:
 	case V4L2_PIX_FMT_UYVY:
 	case V4L2_PIX_FMT_YVYU:
@@ -243,11 +279,29 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_ABGR32:
 		tpg->twopixelsize[0] = 2 * 4;
 		break;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV21M:
+		tpg->twopixelsize[0] = 2;
+		tpg->twopixelsize[1] = 2;
+		break;
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV61:
 	case V4L2_PIX_FMT_NV16M:
 	case V4L2_PIX_FMT_NV61M:
 		tpg->twopixelsize[0] = 2;
 		tpg->twopixelsize[1] = 2;
 		break;
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+	case V4L2_PIX_FMT_YUV420M:
+	case V4L2_PIX_FMT_YVU420M:
+		tpg->twopixelsize[0] = 2;
+		tpg->twopixelsize[1] = 2;
+		tpg->twopixelsize[2] = 2;
+		break;
 	}
 	return true;
 }
@@ -685,6 +739,37 @@ static void gen_twopix(struct tpg_data *tpg,
 	b_v = tpg->colors[color][2]; /* B or precalculated V */
 
 	switch (tpg->fourcc) {
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YUV420M:
+		buf[0][offset] = r_y;
+		if (odd) {
+			buf[1][0] = (buf[1][0] + g_u) / 2;
+			buf[2][0] = (buf[2][0] + b_v) / 2;
+			buf[1][1] = buf[1][0];
+			buf[2][1] = buf[2][0];
+			break;
+		}
+		buf[1][0] = g_u;
+		buf[2][0] = b_v;
+		break;
+	case V4L2_PIX_FMT_YVU420:
+	case V4L2_PIX_FMT_YVU420M:
+		buf[0][offset] = r_y;
+		if (odd) {
+			buf[1][0] = (buf[1][0] + b_v) / 2;
+			buf[2][0] = (buf[2][0] + g_u) / 2;
+			buf[1][1] = buf[1][0];
+			buf[2][1] = buf[2][0];
+			break;
+		}
+		buf[1][0] = b_v;
+		buf[2][0] = g_u;
+		break;
+
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV16M:
 		buf[0][offset] = r_y;
 		if (odd) {
@@ -695,6 +780,9 @@ static void gen_twopix(struct tpg_data *tpg,
 		buf[1][0] = g_u;
 		buf[1][1] = b_v;
 		break;
+	case V4L2_PIX_FMT_NV21:
+	case V4L2_PIX_FMT_NV21M:
+	case V4L2_PIX_FMT_NV61:
 	case V4L2_PIX_FMT_NV61M:
 		buf[0][offset] = r_y;
 		if (odd) {
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 17/29] vivid-tpg: add support for V4L2_PIX_FMT_GREY
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (15 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 16/29] vivid-tpg: add support for more planar formats Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 18/29] vivid-tpg: add helper functions to simplify common calculations Hans Verkuil
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add monochrome support to the TPG.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 19b5806..766cbf5 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -199,6 +199,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_XBGR32:
 	case V4L2_PIX_FMT_ARGB32:
 	case V4L2_PIX_FMT_ABGR32:
+	case V4L2_PIX_FMT_GREY:
 		tpg->is_yuv = false;
 		break;
 	case V4L2_PIX_FMT_YUV420M:
@@ -279,6 +280,9 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_ABGR32:
 		tpg->twopixelsize[0] = 2 * 4;
 		break;
+	case V4L2_PIX_FMT_GREY:
+		tpg->twopixelsize[0] = 2;
+		break;
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV12M:
@@ -598,7 +602,7 @@ static void precalculate_color(struct tpg_data *tpg, int k)
 		g <<= 4;
 		b <<= 4;
 	}
-	if (tpg->qual == TPG_QUAL_GRAY) {
+	if (tpg->qual == TPG_QUAL_GRAY || tpg->fourcc == V4L2_PIX_FMT_GREY) {
 		/* Rec. 709 Luma function */
 		/* (0.2126, 0.7152, 0.0722) * (255 * 256) */
 		r = g = b = (13879 * r + 46688 * g + 4713 * b) >> 16;
@@ -739,6 +743,9 @@ static void gen_twopix(struct tpg_data *tpg,
 	b_v = tpg->colors[color][2]; /* B or precalculated V */
 
 	switch (tpg->fourcc) {
+	case V4L2_PIX_FMT_GREY:
+		buf[0][offset] = r_y;
+		break;
 	case V4L2_PIX_FMT_YUV422P:
 	case V4L2_PIX_FMT_YUV420:
 	case V4L2_PIX_FMT_YUV420M:
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 18/29] vivid-tpg: add helper functions to simplify common calculations
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (16 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 17/29] vivid-tpg: add support for V4L2_PIX_FMT_GREY Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 19/29] vivid-tpg: add const where appropriate Hans Verkuil
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add helper functions to handle horizontal downscaling and horizontal
scaling.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 130 ++++++++++++++-----------------
 drivers/media/platform/vivid/vivid-tpg.h |  23 ++++++
 2 files changed, 80 insertions(+), 73 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 766cbf5..a919363 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -183,6 +183,9 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	tpg->recalc_colors = true;
 	tpg->vdownsampling[0] = 1;
 	tpg->hdownsampling[0] = 1;
+	tpg->hmask[0] = ~0;
+	tpg->hmask[1] = ~0;
+	tpg->hmask[2] = ~0;
 
 	switch (fourcc) {
 	case V4L2_PIX_FMT_RGB565:
@@ -231,6 +234,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_NV61:
 		tpg->vdownsampling[1] = 1;
 		tpg->hdownsampling[1] = 1;
+		tpg->hmask[1] = ~1;
 		tpg->planes = 2;
 		tpg->is_yuv = true;
 		break;
@@ -242,6 +246,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_NV21:
 		tpg->vdownsampling[1] = 2;
 		tpg->hdownsampling[1] = 1;
+		tpg->hmask[1] = ~1;
 		tpg->planes = 2;
 		tpg->is_yuv = true;
 		break;
@@ -249,6 +254,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_UYVY:
 	case V4L2_PIX_FMT_YVYU:
 	case V4L2_PIX_FMT_VYUY:
+		tpg->hmask[0] = ~1;
 		tpg->is_yuv = true;
 		break;
 	default:
@@ -1116,6 +1122,7 @@ static void tpg_calculate_square_border(struct tpg_data *tpg)
 static void tpg_precalculate_line(struct tpg_data *tpg)
 {
 	enum tpg_color contrast;
+	u8 pix[TPG_MAX_PLANES][8];
 	unsigned pat;
 	unsigned p;
 	unsigned x;
@@ -1142,7 +1149,6 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
 		for (x = 0; x < tpg->scaled_width * 2; x += 2) {
 			unsigned real_x = src_x;
 			enum tpg_color color1, color2;
-			u8 pix[TPG_MAX_PLANES][8];
 
 			real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x;
 			color1 = tpg_get_color(tpg, pat, real_x);
@@ -1170,8 +1176,7 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
 			for (p = 0; p < tpg->planes; p++) {
 				unsigned twopixsize = tpg->twopixelsize[p];
 				unsigned hdiv = tpg->hdownsampling[p];
-				u8 *pos = tpg->lines[pat][p] +
-						(x / hdiv) * twopixsize / 2;
+				u8 *pos = tpg->lines[pat][p] + tpg_hdiv(tpg, p, x);
 
 				memcpy(pos, pix[p], twopixsize / hdiv);
 			}
@@ -1185,50 +1190,38 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
 			unsigned next_pat = (pat + 1) % pat_lines;
 
 			for (p = 1; p < tpg->planes; p++) {
-				unsigned twopixsize = tpg->twopixelsize[p];
-				unsigned hdiv = tpg->hdownsampling[p];
-
-				for (x = 0; x < tpg->scaled_width * 2; x += 2) {
-					unsigned offset = (x / hdiv) * twopixsize / 2;
-					u8 *pos1 = tpg->lines[pat][p] + offset;
-					u8 *pos2 = tpg->lines[next_pat][p] + offset;
-					u8 *dest = tpg->downsampled_lines[pat][p] + offset;
-					unsigned i;
+				unsigned w = tpg_hdiv(tpg, p, tpg->scaled_width * 2);
+				u8 *pos1 = tpg->lines[pat][p];
+				u8 *pos2 = tpg->lines[next_pat][p];
+				u8 *dest = tpg->downsampled_lines[pat][p];
 
-					for (i = 0; i < twopixsize / hdiv; i++, dest++, pos1++, pos2++)
-						*dest = ((u16)*pos1 + (u16)*pos2) / 2;
-				}
+				for (x = 0; x < w; x++, pos1++, pos2++, dest++)
+					*dest = ((u16)*pos1 + (u16)*pos2) / 2;
 			}
 		}
 	}
 
-	for (x = 0; x < tpg->scaled_width; x += 2) {
-		u8 pix[TPG_MAX_PLANES][8];
-
-		gen_twopix(tpg, pix, contrast, 0);
-		gen_twopix(tpg, pix, contrast, 1);
-		for (p = 0; p < tpg->planes; p++) {
-			unsigned twopixsize = tpg->twopixelsize[p];
-			u8 *pos = tpg->contrast_line[p] + x * twopixsize / 2;
+	gen_twopix(tpg, pix, contrast, 0);
+	gen_twopix(tpg, pix, contrast, 1);
+	for (p = 0; p < tpg->planes; p++) {
+		unsigned twopixsize = tpg->twopixelsize[p];
+		u8 *pos = tpg->contrast_line[p];
 
+		for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
 			memcpy(pos, pix[p], twopixsize);
-		}
 	}
-	for (x = 0; x < tpg->scaled_width; x += 2) {
-		u8 pix[TPG_MAX_PLANES][8];
 
-		gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0);
-		gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1);
-		for (p = 0; p < tpg->planes; p++) {
-			unsigned twopixsize = tpg->twopixelsize[p];
-			u8 *pos = tpg->black_line[p] + x * twopixsize / 2;
+	gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0);
+	gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1);
+	for (p = 0; p < tpg->planes; p++) {
+		unsigned twopixsize = tpg->twopixelsize[p];
+		u8 *pos = tpg->black_line[p];
 
+		for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
 			memcpy(pos, pix[p], twopixsize);
-		}
 	}
-	for (x = 0; x < tpg->scaled_width * 2; x += 2) {
-		u8 pix[TPG_MAX_PLANES][8];
 
+	for (x = 0; x < tpg->scaled_width * 2; x += 2) {
 		gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 0);
 		gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 1);
 		for (p = 0; p < tpg->planes; p++) {
@@ -1238,6 +1231,7 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
 			memcpy(pos, pix[p], twopixsize);
 		}
 	}
+
 	gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 0);
 	gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 1);
 	gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 0);
@@ -1529,9 +1523,8 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	int hmax = (tpg->compose.height * tpg->perc_fill) / 100;
 	int h;
 	unsigned twopixsize = tpg->twopixelsize[p];
-	unsigned hdiv = tpg->hdownsampling[p];
 	unsigned vdiv = tpg->vdownsampling[p];
-	unsigned img_width = (tpg->compose.width / hdiv) * twopixsize / 2;
+	unsigned img_width = tpg_hdiv(tpg, p, tpg->compose.width);
 	unsigned line_offset;
 	unsigned left_pillar_width = 0;
 	unsigned right_pillar_start = img_width;
@@ -1547,28 +1540,25 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 
 	tpg_recalc(tpg);
 
-	mv_hor_old = (mv_hor_old * tpg->scaled_width / tpg->src_width) & ~1;
-	mv_hor_new = (mv_hor_new * tpg->scaled_width / tpg->src_width) & ~1;
+	mv_hor_old = tpg_hscale_div(tpg, p, mv_hor_old);
+	mv_hor_new = tpg_hscale_div(tpg, p, mv_hor_new);
 	wss_width = tpg->crop.left < tpg->src_width / 2 ?
 			tpg->src_width / 2 - tpg->crop.left : 0;
 	if (wss_width > tpg->crop.width)
 		wss_width = tpg->crop.width;
-	wss_width = wss_width * tpg->scaled_width / tpg->src_width;
+	wss_width = tpg_hscale_div(tpg, p, wss_width);
 
-	vbuf += tpg->compose.left * twopixsize / 2;
-	line_offset = tpg->crop.left * tpg->scaled_width / tpg->src_width;
-	line_offset = ((line_offset & ~1) / hdiv) * twopixsize / 2;
+	vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
+	line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
 	if (tpg->crop.left < tpg->border.left) {
 		left_pillar_width = tpg->border.left - tpg->crop.left;
 		if (left_pillar_width > tpg->crop.width)
 			left_pillar_width = tpg->crop.width;
-		left_pillar_width = (left_pillar_width * tpg->scaled_width) / tpg->src_width;
-		left_pillar_width = ((left_pillar_width & ~1) / hdiv) * twopixsize / 2;
+		left_pillar_width = tpg_hscale_div(tpg, p, left_pillar_width);
 	}
 	if (tpg->crop.left + tpg->crop.width > tpg->border.left + tpg->border.width) {
 		right_pillar_start = tpg->border.left + tpg->border.width - tpg->crop.left;
-		right_pillar_start = (right_pillar_start * tpg->scaled_width) / tpg->src_width;
-		right_pillar_start = ((right_pillar_start & ~1) / hdiv) * twopixsize / 2;
+		right_pillar_start = tpg_hscale_div(tpg, p, right_pillar_start);
 		if (right_pillar_start > img_width)
 			right_pillar_start = img_width;
 	}
@@ -1651,10 +1641,8 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 
 			pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
 			pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
-			linestart_older = tpg->lines[pat_line_old][p] +
-				(mv_hor_old / hdiv) * twopixsize / 2;
-			linestart_newer = tpg->lines[pat_line_new][p] +
-				(mv_hor_new / hdiv) * twopixsize / 2;
+			linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
+			linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
 
 			if (vdiv > 1) {
 				unsigned frame_line_next;
@@ -1679,8 +1667,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 					avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
 					if (avg_pat < 0)
 						break;
-					linestart_older = tpg->downsampled_lines[avg_pat][p] +
-						(mv_hor_old / hdiv) * twopixsize / 2;
+					linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
 					linestart_newer = linestart_older;
 					break;
 				case V4L2_FIELD_NONE:
@@ -1691,11 +1678,11 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 					avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
 					if (avg_pat >= 0)
 						linestart_older = tpg->downsampled_lines[avg_pat][p] +
-							(mv_hor_old / hdiv) * twopixsize / 2;
+							mv_hor_old;
 					avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
 					if (avg_pat >= 0)
 						linestart_newer = tpg->downsampled_lines[avg_pat][p] +
-							(mv_hor_new / hdiv) * twopixsize / 2;
+							mv_hor_new;
 					break;
 				}
 			}
@@ -1739,22 +1726,10 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			memcpy(vbuf + buf_line * stride, linestart_older, img_width);
 			break;
 		}
-
-		if (is_tv && !is_60hz && frame_line == 0 && wss_width) {
-			/*
-			 * Replace the first half of the top line of a 50 Hz frame
-			 * with random data to simulate a WSS signal.
-			 */
-			u8 *wss = tpg->random_line[p] +
-				  twopixsize * prandom_u32_max(tpg->src_width / 2);
-
-			memcpy(vbuf + buf_line * stride, wss,
-			       (wss_width / hdiv) * twopixsize / 2);
-		}
 	}
 
 	vbuf = orig_vbuf;
-	vbuf += (tpg->compose.left / hdiv) * twopixsize / 2;
+	vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
 	src_y = 0;
 	error = 0;
 	for (h = 0; h < tpg->compose.height; h++) {
@@ -1777,6 +1752,17 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			buf_line /= vdiv;
 		}
 
+		if (is_tv && !is_60hz && frame_line == 0 && wss_width) {
+			/*
+			 * Replace the first half of the top line of a 50 Hz frame
+			 * with random data to simulate a WSS signal.
+			 */
+			u8 *wss = tpg->random_line[p] +
+				  twopixsize * prandom_u32_max(tpg->src_width / 2);
+
+			memcpy(vbuf + buf_line * stride, wss, wss_width);
+		}
+
 		if (tpg->show_border && frame_line >= b->top &&
 		    frame_line < b->top + b->height) {
 			unsigned bottom = b->top + b->height - 1;
@@ -1818,14 +1804,12 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			if (c->left + c->width < left + width)
 				width -= left + width - c->left - c->width;
 			left -= c->left;
-			left = (left * tpg->scaled_width) / tpg->src_width;
-			left = ((left & ~1) / hdiv) * twopixsize / 2;
-			width = (width * tpg->scaled_width) / tpg->src_width;
-			width = ((width & ~1) / hdiv) * twopixsize / 2;
+			left = tpg_hscale_div(tpg, p, left);
+			width = tpg_hscale_div(tpg, p, width);
 			memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], width);
 		}
 		if (tpg->insert_sav) {
-			unsigned offset = (tpg->compose.width / (6 * hdiv)) * twopixsize;
+			unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width / 3);
 			u8 *p = vbuf + buf_line * stride + offset;
 			unsigned vact = 0, hact = 0;
 
@@ -1839,7 +1823,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 				(hact ^ vact ^ f);
 		}
 		if (tpg->insert_eav) {
-			unsigned offset = (tpg->compose.width / (6 * hdiv)) * 2 * twopixsize;
+			unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width * 2 / 3);
 			u8 *p = vbuf + buf_line * stride + offset;
 			unsigned vact = 0, hact = 1;
 
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index 5a53eb9..b62f392 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -142,6 +142,11 @@ struct tpg_data {
 	unsigned			planes;
 	u8				vdownsampling[TPG_MAX_PLANES];
 	u8				hdownsampling[TPG_MAX_PLANES];
+	/*
+	 * horizontal positions must be ANDed with this value to enforce
+	 * correct boundaries for packed YUYV values.
+	 */
+	unsigned			hmask[TPG_MAX_PLANES];
 	/* Used to store the colors in native format, either RGB or YUV */
 	u8				colors[TPG_COLOR_MAX][3];
 	u8				textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8];
@@ -347,6 +352,24 @@ static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned p
 	return tpg->twopixelsize[plane];
 }
 
+static inline unsigned tpg_hdiv(const struct tpg_data *tpg,
+				  unsigned plane, unsigned x)
+{
+	return ((x / tpg->hdownsampling[plane]) & tpg->hmask[plane]) *
+		tpg->twopixelsize[plane] / 2;
+}
+
+static inline unsigned tpg_hscale(const struct tpg_data *tpg, unsigned x)
+{
+	return (x * tpg->scaled_width) / tpg->src_width;
+}
+
+static inline unsigned tpg_hscale_div(const struct tpg_data *tpg,
+				      unsigned plane, unsigned x)
+{
+	return tpg_hdiv(tpg, plane, tpg_hscale(tpg, x));
+}
+
 static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned plane)
 {
 	return tpg->bytesperline[plane];
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 19/29] vivid-tpg: add const where appropriate
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (17 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 18/29] vivid-tpg: add helper functions to simplify common calculations Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 20/29] vivid-tpg: add a new tpg_draw_params structure Hans Verkuil
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Added 'const' to several functions where that is possible to do.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 8 ++++----
 drivers/media/platform/vivid/vivid-tpg.h | 8 +++++---
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index a919363..2f78ccd 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1241,8 +1241,8 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
 /* need this to do rgb24 rendering */
 typedef struct { u16 __; u8 _; } __packed x24;
 
-void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
-		int y, int x, char *text)
+void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
+		  int y, int x, char *text)
 {
 	int line;
 	unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
@@ -1389,7 +1389,7 @@ void tpg_update_mv_step(struct tpg_data *tpg)
 }
 
 /* Map the line number relative to the crop rectangle to a frame line number */
-static unsigned tpg_calc_frameline(struct tpg_data *tpg, unsigned src_y,
+static unsigned tpg_calc_frameline(const struct tpg_data *tpg, unsigned src_y,
 				    unsigned field)
 {
 	switch (field) {
@@ -1406,7 +1406,7 @@ static unsigned tpg_calc_frameline(struct tpg_data *tpg, unsigned src_y,
  * Map the line number relative to the compose rectangle to a destination
  * buffer line number.
  */
-static unsigned tpg_calc_buffer_line(struct tpg_data *tpg, unsigned y,
+static unsigned tpg_calc_buffer_line(const struct tpg_data *tpg, unsigned y,
 				    unsigned field)
 {
 	y += tpg->compose.top;
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index b62f392..82ce9bf 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -193,12 +193,14 @@ void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
 		       u32 field);
 
 void tpg_set_font(const u8 *f);
-void tpg_gen_text(struct tpg_data *tpg,
+void tpg_gen_text(const struct tpg_data *tpg,
 		u8 *basep[TPG_MAX_PLANES][2], int y, int x, char *text);
 void tpg_calc_text_basep(struct tpg_data *tpg,
 		u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf);
-void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf);
-void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf);
+void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
+			   unsigned p, u8 *vbuf);
+void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std,
+		    unsigned p, u8 *vbuf);
 bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc);
 void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
 		const struct v4l2_rect *compose);
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 20/29] vivid-tpg: add a new tpg_draw_params structure
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (18 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 19/29] vivid-tpg: add const where appropriate Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 21/29] vivid-tpg: move common parameters to tpg_draw_params Hans Verkuil
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This is needed to refactor the drawing function which is much too big.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 2f78ccd..acee705 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1510,6 +1510,35 @@ static int tpg_pattern_avg(const struct tpg_data *tpg,
 	return -1;
 }
 
+/*
+ * This struct contains common parameters used by both the drawing of the
+ * test pattern and the drawing of the extras (borders, square, etc.)
+ */
+struct tpg_draw_params {
+	/* common data */
+	bool is_tv;
+	bool is_60hz;
+	unsigned twopixsize;
+	unsigned img_width;
+	unsigned stride;
+	unsigned hmax;
+	unsigned frame_line;
+	unsigned frame_line_next;
+
+	/* test pattern */
+	unsigned mv_hor_old;
+	unsigned mv_hor_new;
+	unsigned mv_vert_old;
+	unsigned mv_vert_new;
+
+	/* extras */
+	unsigned wss_width;
+	unsigned wss_random_offset;
+	unsigned sav_eav_f;
+	unsigned left_pillar_width;
+	unsigned right_pillar_start;
+};
+
 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 {
 	bool is_tv = std;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 21/29] vivid-tpg: move common parameters to tpg_draw_params
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (19 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 20/29] vivid-tpg: add a new tpg_draw_params structure Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 22/29] vivid-tpg: move pattern-related fields to struct tpg_draw_params Hans Verkuil
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Replace local variables by fields in the tpg_draw_params struct.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 34 +++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index acee705..1e5eefa 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1541,23 +1541,21 @@ struct tpg_draw_params {
 
 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 {
-	bool is_tv = std;
-	bool is_60hz = is_tv && (std & V4L2_STD_525_60);
+	struct tpg_draw_params params;
 	unsigned mv_hor_old = tpg->mv_hor_count % tpg->src_width;
 	unsigned mv_hor_new = (tpg->mv_hor_count + tpg->mv_hor_step) % tpg->src_width;
 	unsigned mv_vert_old = tpg->mv_vert_count % tpg->src_height;
 	unsigned mv_vert_new = (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
 	unsigned wss_width;
 	unsigned f;
-	int hmax = (tpg->compose.height * tpg->perc_fill) / 100;
 	int h;
-	unsigned twopixsize = tpg->twopixelsize[p];
+	unsigned twopixsize;
 	unsigned vdiv = tpg->vdownsampling[p];
-	unsigned img_width = tpg_hdiv(tpg, p, tpg->compose.width);
+	unsigned img_width;
 	unsigned line_offset;
 	unsigned left_pillar_width = 0;
-	unsigned right_pillar_start = img_width;
-	unsigned stride = tpg->bytesperline[p];
+	unsigned right_pillar_start;
+	unsigned stride;
 	unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
 	u8 *orig_vbuf = vbuf;
 
@@ -1569,6 +1567,17 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 
 	tpg_recalc(tpg);
 
+	params.is_tv = std;
+	params.is_60hz = std & V4L2_STD_525_60;
+	params.twopixsize = tpg->twopixelsize[p];
+	params.img_width = tpg_hdiv(tpg, p, tpg->compose.width);
+	params.stride = tpg->bytesperline[p];
+	params.hmax = (tpg->compose.height * tpg->perc_fill) / 100;
+
+	twopixsize = params.twopixsize;
+	img_width = params.img_width;
+	stride = params.stride;
+
 	mv_hor_old = tpg_hscale_div(tpg, p, mv_hor_old);
 	mv_hor_new = tpg_hscale_div(tpg, p, mv_hor_new);
 	wss_width = tpg->crop.left < tpg->src_width / 2 ?
@@ -1585,6 +1594,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			left_pillar_width = tpg->crop.width;
 		left_pillar_width = tpg_hscale_div(tpg, p, left_pillar_width);
 	}
+	right_pillar_start = img_width;
 	if (tpg->crop.left + tpg->crop.width > tpg->border.left + tpg->border.width) {
 		right_pillar_start = tpg->border.left + tpg->border.width - tpg->crop.left;
 		right_pillar_start = tpg_hscale_div(tpg, p, right_pillar_start);
@@ -1592,7 +1602,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			right_pillar_start = img_width;
 	}
 
-	f = tpg->field == (is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+	f = tpg->field == (params.is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
 
 	for (h = 0; h < tpg->compose.height; h++) {
 		bool even;
@@ -1636,8 +1646,8 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			buf_line /= vdiv;
 		}
 
-		if (h >= hmax) {
-			if (hmax == tpg->compose.height)
+		if (h >= params.hmax) {
+			if (params.hmax == tpg->compose.height)
 				continue;
 			if (!tpg->perc_fill_blank)
 				continue;
@@ -1720,7 +1730,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 		}
 		if (tpg->field_alternate) {
 			linestart_top = linestart_bottom = linestart_older;
-		} else if (is_60hz) {
+		} else if (params.is_60hz) {
 			linestart_top = linestart_newer;
 			linestart_bottom = linestart_older;
 		} else {
@@ -1781,7 +1791,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			buf_line /= vdiv;
 		}
 
-		if (is_tv && !is_60hz && frame_line == 0 && wss_width) {
+		if (params.is_tv && !params.is_60hz && frame_line == 0 && wss_width) {
 			/*
 			 * Replace the first half of the top line of a 50 Hz frame
 			 * with random data to simulate a WSS signal.
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 22/29] vivid-tpg: move pattern-related fields to struct tpg_draw_params
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (20 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 21/29] vivid-tpg: move common parameters to tpg_draw_params Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 23/29] vivid-tpg: move 'extras' parameters to tpg_draw_params Hans Verkuil
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add a new function that fills in pattern-related fields in struct
tpg_draw_params.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 1e5eefa..c477730 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1539,13 +1539,26 @@ struct tpg_draw_params {
 	unsigned right_pillar_start;
 };
 
+static void tpg_fill_params_pattern(const struct tpg_data *tpg, unsigned p,
+				    struct tpg_draw_params *params)
+{
+	params->mv_hor_old =
+		tpg_hscale_div(tpg, p, tpg->mv_hor_count % tpg->src_width);
+	params->mv_hor_new =
+		tpg_hscale_div(tpg, p, (tpg->mv_hor_count + tpg->mv_hor_step) %
+			       tpg->src_width);
+	params->mv_vert_old = tpg->mv_vert_count % tpg->src_height;
+	params->mv_vert_new =
+		(tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
+}
+
 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 {
 	struct tpg_draw_params params;
-	unsigned mv_hor_old = tpg->mv_hor_count % tpg->src_width;
-	unsigned mv_hor_new = (tpg->mv_hor_count + tpg->mv_hor_step) % tpg->src_width;
-	unsigned mv_vert_old = tpg->mv_vert_count % tpg->src_height;
-	unsigned mv_vert_new = (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
+	unsigned mv_hor_old;
+	unsigned mv_hor_new;
+	unsigned mv_vert_old;
+	unsigned mv_vert_new;
 	unsigned wss_width;
 	unsigned f;
 	int h;
@@ -1574,12 +1587,17 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	params.stride = tpg->bytesperline[p];
 	params.hmax = (tpg->compose.height * tpg->perc_fill) / 100;
 
+	tpg_fill_params_pattern(tpg, p, &params);
+
+	mv_hor_old = params.mv_hor_old;
+	mv_hor_new = params.mv_hor_new;
+	mv_vert_old = params.mv_vert_old;
+	mv_vert_new = params.mv_vert_new;
+
 	twopixsize = params.twopixsize;
 	img_width = params.img_width;
 	stride = params.stride;
 
-	mv_hor_old = tpg_hscale_div(tpg, p, mv_hor_old);
-	mv_hor_new = tpg_hscale_div(tpg, p, mv_hor_new);
 	wss_width = tpg->crop.left < tpg->src_width / 2 ?
 			tpg->src_width / 2 - tpg->crop.left : 0;
 	if (wss_width > tpg->crop.width)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 23/29] vivid-tpg: move 'extras' parameters to tpg_draw_params
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (21 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 22/29] vivid-tpg: move pattern-related fields to struct tpg_draw_params Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 24/29] vivid-tpg: move the 'extras' drawing to a separate function Hans Verkuil
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Any parameters related to drawing 'extras' like the border, the square,
etc. are moved to struct tpg_draw_params.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 100 ++++++++++++++++++-------------
 1 file changed, 58 insertions(+), 42 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index c477730..a738ce1 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1552,6 +1552,44 @@ static void tpg_fill_params_pattern(const struct tpg_data *tpg, unsigned p,
 		(tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
 }
 
+static void tpg_fill_params_extras(const struct tpg_data *tpg,
+				   unsigned p,
+				   struct tpg_draw_params *params)
+{
+	unsigned left_pillar_width = 0;
+	unsigned right_pillar_start = params->img_width;
+
+	params->wss_width = tpg->crop.left < tpg->src_width / 2 ?
+		tpg->src_width / 2 - tpg->crop.left : 0;
+	if (params->wss_width > tpg->crop.width)
+		params->wss_width = tpg->crop.width;
+	params->wss_width = tpg_hscale_div(tpg, p, params->wss_width);
+	params->wss_random_offset =
+		params->twopixsize * prandom_u32_max(tpg->src_width / 2);
+
+	if (tpg->crop.left < tpg->border.left) {
+		left_pillar_width = tpg->border.left - tpg->crop.left;
+		if (left_pillar_width > tpg->crop.width)
+			left_pillar_width = tpg->crop.width;
+		left_pillar_width = tpg_hscale_div(tpg, p, left_pillar_width);
+	}
+	params->left_pillar_width = left_pillar_width;
+
+	if (tpg->crop.left + tpg->crop.width >
+	    tpg->border.left + tpg->border.width) {
+		right_pillar_start =
+			tpg->border.left + tpg->border.width - tpg->crop.left;
+		right_pillar_start =
+			tpg_hscale_div(tpg, p, right_pillar_start);
+		if (right_pillar_start > params->img_width)
+			right_pillar_start = params->img_width;
+	}
+	params->right_pillar_start = right_pillar_start;
+
+	params->sav_eav_f = tpg->field ==
+			(params->is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+}
+
 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 {
 	struct tpg_draw_params params;
@@ -1559,15 +1597,11 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	unsigned mv_hor_new;
 	unsigned mv_vert_old;
 	unsigned mv_vert_new;
-	unsigned wss_width;
-	unsigned f;
 	int h;
 	unsigned twopixsize;
 	unsigned vdiv = tpg->vdownsampling[p];
 	unsigned img_width;
 	unsigned line_offset;
-	unsigned left_pillar_width = 0;
-	unsigned right_pillar_start;
 	unsigned stride;
 	unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
 	u8 *orig_vbuf = vbuf;
@@ -1594,33 +1628,14 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	mv_vert_old = params.mv_vert_old;
 	mv_vert_new = params.mv_vert_new;
 
+	tpg_fill_params_extras(tpg, p, &params);
+
 	twopixsize = params.twopixsize;
 	img_width = params.img_width;
 	stride = params.stride;
 
-	wss_width = tpg->crop.left < tpg->src_width / 2 ?
-			tpg->src_width / 2 - tpg->crop.left : 0;
-	if (wss_width > tpg->crop.width)
-		wss_width = tpg->crop.width;
-	wss_width = tpg_hscale_div(tpg, p, wss_width);
-
 	vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
 	line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
-	if (tpg->crop.left < tpg->border.left) {
-		left_pillar_width = tpg->border.left - tpg->crop.left;
-		if (left_pillar_width > tpg->crop.width)
-			left_pillar_width = tpg->crop.width;
-		left_pillar_width = tpg_hscale_div(tpg, p, left_pillar_width);
-	}
-	right_pillar_start = img_width;
-	if (tpg->crop.left + tpg->crop.width > tpg->border.left + tpg->border.width) {
-		right_pillar_start = tpg->border.left + tpg->border.width - tpg->crop.left;
-		right_pillar_start = tpg_hscale_div(tpg, p, right_pillar_start);
-		if (right_pillar_start > img_width)
-			right_pillar_start = img_width;
-	}
-
-	f = tpg->field == (params.is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
 
 	for (h = 0; h < tpg->compose.height; h++) {
 		bool even;
@@ -1809,22 +1824,21 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			buf_line /= vdiv;
 		}
 
-		if (params.is_tv && !params.is_60hz && frame_line == 0 && wss_width) {
+		if (params.is_tv && !params.is_60hz && frame_line == 0 && params.wss_width) {
 			/*
 			 * Replace the first half of the top line of a 50 Hz frame
 			 * with random data to simulate a WSS signal.
 			 */
-			u8 *wss = tpg->random_line[p] +
-				  twopixsize * prandom_u32_max(tpg->src_width / 2);
+			u8 *wss = tpg->random_line[p] + params.wss_random_offset;
 
-			memcpy(vbuf + buf_line * stride, wss, wss_width);
+			memcpy(vbuf + buf_line * stride, wss, params.wss_width);
 		}
 
 		if (tpg->show_border && frame_line >= b->top &&
 		    frame_line < b->top + b->height) {
 			unsigned bottom = b->top + b->height - 1;
-			unsigned left = left_pillar_width;
-			unsigned right = right_pillar_start;
+			unsigned left = params.left_pillar_width;
+			unsigned right = params.right_pillar_start;
 
 			if (frame_line == b->top || frame_line == b->top + 1 ||
 			    frame_line == bottom || frame_line == bottom - 1) {
@@ -1843,9 +1857,9 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 		}
 		if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top &&
 		    frame_line < b->top + b->height) {
-			memcpy(vbuf + buf_line * stride, tpg->black_line[p], left_pillar_width);
-			memcpy(vbuf + buf_line * stride + right_pillar_start, tpg->black_line[p],
-			       img_width - right_pillar_start);
+			memcpy(vbuf + buf_line * stride, tpg->black_line[p], params.left_pillar_width);
+			memcpy(vbuf + buf_line * stride + params.right_pillar_start, tpg->black_line[p],
+			       img_width - params.right_pillar_start);
 		}
 		if (tpg->show_square && frame_line >= sq->top &&
 		    frame_line < sq->top + sq->height &&
@@ -1873,11 +1887,12 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			p[0] = 0xff;
 			p[1] = 0;
 			p[2] = 0;
-			p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) |
+			p[3] = 0x80 | (params.sav_eav_f << 6) |
+				(vact << 5) | (hact << 4) |
 				((hact ^ vact) << 3) |
-				((hact ^ f) << 2) |
-				((f ^ vact) << 1) |
-				(hact ^ vact ^ f);
+				((hact ^ params.sav_eav_f) << 2) |
+				((params.sav_eav_f ^ vact) << 1) |
+				(hact ^ vact ^ params.sav_eav_f);
 		}
 		if (tpg->insert_eav) {
 			unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width * 2 / 3);
@@ -1887,11 +1902,12 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			p[0] = 0xff;
 			p[1] = 0;
 			p[2] = 0;
-			p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) |
+			p[3] = 0x80 | (params.sav_eav_f << 6) |
+				(vact << 5) | (hact << 4) |
 				((hact ^ vact) << 3) |
-				((hact ^ f) << 2) |
-				((f ^ vact) << 1) |
-				(hact ^ vact ^ f);
+				((hact ^ params.sav_eav_f) << 2) |
+				((params.sav_eav_f ^ vact) << 1) |
+				(hact ^ vact ^ params.sav_eav_f);
 		}
 	}
 }
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 24/29] vivid-tpg: move the 'extras' drawing to a separate function
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (22 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 23/29] vivid-tpg: move 'extras' parameters to tpg_draw_params Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 25/29] vivid-tpg: split off the pattern drawing code Hans Verkuil
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This moves the drawing code for the extras (border, square, etc) to
a function of its own instead of having this in the main for loop.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 216 +++++++++++++++----------------
 1 file changed, 104 insertions(+), 112 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index a738ce1..5ff9db9 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1590,6 +1590,105 @@ static void tpg_fill_params_extras(const struct tpg_data *tpg,
 			(params->is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
 }
 
+static void tpg_fill_plane_extras(const struct tpg_data *tpg,
+				  const struct tpg_draw_params *params,
+				  unsigned p, unsigned h, u8 *vbuf)
+{
+	unsigned twopixsize = params->twopixsize;
+	unsigned img_width = params->img_width;
+	unsigned frame_line = params->frame_line;
+	const struct v4l2_rect *sq = &tpg->square;
+	const struct v4l2_rect *b = &tpg->border;
+	const struct v4l2_rect *c = &tpg->crop;
+
+	if (params->is_tv && !params->is_60hz &&
+	    frame_line == 0 && params->wss_width) {
+		/*
+		 * Replace the first half of the top line of a 50 Hz frame
+		 * with random data to simulate a WSS signal.
+		 */
+		u8 *wss = tpg->random_line[p] + params->wss_random_offset;
+
+		memcpy(vbuf, wss, params->wss_width);
+	}
+
+	if (tpg->show_border && frame_line >= b->top &&
+	    frame_line < b->top + b->height) {
+		unsigned bottom = b->top + b->height - 1;
+		unsigned left = params->left_pillar_width;
+		unsigned right = params->right_pillar_start;
+
+		if (frame_line == b->top || frame_line == b->top + 1 ||
+		    frame_line == bottom || frame_line == bottom - 1) {
+			memcpy(vbuf + left, tpg->contrast_line[p],
+					right - left);
+		} else {
+			if (b->left >= c->left &&
+			    b->left < c->left + c->width)
+				memcpy(vbuf + left,
+					tpg->contrast_line[p], twopixsize);
+			if (b->left + b->width > c->left &&
+			    b->left + b->width <= c->left + c->width)
+				memcpy(vbuf + right - twopixsize,
+					tpg->contrast_line[p], twopixsize);
+		}
+	}
+	if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top &&
+	    frame_line < b->top + b->height) {
+		memcpy(vbuf, tpg->black_line[p], params->left_pillar_width);
+		memcpy(vbuf + params->right_pillar_start, tpg->black_line[p],
+		       img_width - params->right_pillar_start);
+	}
+	if (tpg->show_square && frame_line >= sq->top &&
+	    frame_line < sq->top + sq->height &&
+	    sq->left < c->left + c->width &&
+	    sq->left + sq->width >= c->left) {
+		unsigned left = sq->left;
+		unsigned width = sq->width;
+
+		if (c->left > left) {
+			width -= c->left - left;
+			left = c->left;
+		}
+		if (c->left + c->width < left + width)
+			width -= left + width - c->left - c->width;
+		left -= c->left;
+		left = tpg_hscale_div(tpg, p, left);
+		width = tpg_hscale_div(tpg, p, width);
+		memcpy(vbuf + left, tpg->contrast_line[p], width);
+	}
+	if (tpg->insert_sav) {
+		unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width / 3);
+		u8 *p = vbuf + offset;
+		unsigned vact = 0, hact = 0;
+
+		p[0] = 0xff;
+		p[1] = 0;
+		p[2] = 0;
+		p[3] = 0x80 | (params->sav_eav_f << 6) |
+			(vact << 5) | (hact << 4) |
+			((hact ^ vact) << 3) |
+			((hact ^ params->sav_eav_f) << 2) |
+			((params->sav_eav_f ^ vact) << 1) |
+			(hact ^ vact ^ params->sav_eav_f);
+	}
+	if (tpg->insert_eav) {
+		unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width * 2 / 3);
+		u8 *p = vbuf + offset;
+		unsigned vact = 0, hact = 1;
+
+		p[0] = 0xff;
+		p[1] = 0;
+		p[2] = 0;
+		p[3] = 0x80 | (params->sav_eav_f << 6) |
+			(vact << 5) | (hact << 4) |
+			((hact ^ vact) << 3) |
+			((hact ^ params->sav_eav_f) << 2) |
+			((params->sav_eav_f ^ vact) << 1) |
+			(hact ^ vact ^ params->sav_eav_f);
+	}
+}
+
 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
 {
 	struct tpg_draw_params params;
@@ -1604,7 +1703,6 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	unsigned line_offset;
 	unsigned stride;
 	unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
-	u8 *orig_vbuf = vbuf;
 
 	/* Coarse scaling with Bresenham */
 	unsigned int_part = (tpg->crop.height / factor) / tpg->compose.height;
@@ -1649,7 +1747,9 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 		u8 *linestart_top;
 		u8 *linestart_bottom;
 
-		frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
+		params.frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
+		params.frame_line_next = params.frame_line;
+		frame_line = params.frame_line;
 		even = !(frame_line & 1);
 		buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
 		src_y += int_part;
@@ -1798,117 +1898,9 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			memcpy(vbuf + buf_line * stride, linestart_older, img_width);
 			break;
 		}
-	}
 
-	vbuf = orig_vbuf;
-	vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
-	src_y = 0;
-	error = 0;
-	for (h = 0; h < tpg->compose.height; h++) {
-		unsigned frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
-		unsigned buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
-		const struct v4l2_rect *sq = &tpg->square;
-		const struct v4l2_rect *b = &tpg->border;
-		const struct v4l2_rect *c = &tpg->crop;
-
-		src_y += int_part;
-		error += fract_part;
-		if (error >= tpg->compose.height) {
-			error -= tpg->compose.height;
-			src_y++;
-		}
-
-		if (vdiv > 1) {
-			if (h & 1)
-				continue;
-			buf_line /= vdiv;
-		}
-
-		if (params.is_tv && !params.is_60hz && frame_line == 0 && params.wss_width) {
-			/*
-			 * Replace the first half of the top line of a 50 Hz frame
-			 * with random data to simulate a WSS signal.
-			 */
-			u8 *wss = tpg->random_line[p] + params.wss_random_offset;
-
-			memcpy(vbuf + buf_line * stride, wss, params.wss_width);
-		}
-
-		if (tpg->show_border && frame_line >= b->top &&
-		    frame_line < b->top + b->height) {
-			unsigned bottom = b->top + b->height - 1;
-			unsigned left = params.left_pillar_width;
-			unsigned right = params.right_pillar_start;
-
-			if (frame_line == b->top || frame_line == b->top + 1 ||
-			    frame_line == bottom || frame_line == bottom - 1) {
-				memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p],
-						right - left);
-			} else {
-				if (b->left >= c->left &&
-				    b->left < c->left + c->width)
-					memcpy(vbuf + buf_line * stride + left,
-						tpg->contrast_line[p], twopixsize);
-				if (b->left + b->width > c->left &&
-				    b->left + b->width <= c->left + c->width)
-					memcpy(vbuf + buf_line * stride + right - twopixsize,
-						tpg->contrast_line[p], twopixsize);
-			}
-		}
-		if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top &&
-		    frame_line < b->top + b->height) {
-			memcpy(vbuf + buf_line * stride, tpg->black_line[p], params.left_pillar_width);
-			memcpy(vbuf + buf_line * stride + params.right_pillar_start, tpg->black_line[p],
-			       img_width - params.right_pillar_start);
-		}
-		if (tpg->show_square && frame_line >= sq->top &&
-		    frame_line < sq->top + sq->height &&
-		    sq->left < c->left + c->width &&
-		    sq->left + sq->width >= c->left) {
-			unsigned left = sq->left;
-			unsigned width = sq->width;
-
-			if (c->left > left) {
-				width -= c->left - left;
-				left = c->left;
-			}
-			if (c->left + c->width < left + width)
-				width -= left + width - c->left - c->width;
-			left -= c->left;
-			left = tpg_hscale_div(tpg, p, left);
-			width = tpg_hscale_div(tpg, p, width);
-			memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], width);
-		}
-		if (tpg->insert_sav) {
-			unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width / 3);
-			u8 *p = vbuf + buf_line * stride + offset;
-			unsigned vact = 0, hact = 0;
-
-			p[0] = 0xff;
-			p[1] = 0;
-			p[2] = 0;
-			p[3] = 0x80 | (params.sav_eav_f << 6) |
-				(vact << 5) | (hact << 4) |
-				((hact ^ vact) << 3) |
-				((hact ^ params.sav_eav_f) << 2) |
-				((params.sav_eav_f ^ vact) << 1) |
-				(hact ^ vact ^ params.sav_eav_f);
-		}
-		if (tpg->insert_eav) {
-			unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width * 2 / 3);
-			u8 *p = vbuf + buf_line * stride + offset;
-			unsigned vact = 0, hact = 1;
-
-			p[0] = 0xff;
-			p[1] = 0;
-			p[2] = 0;
-			p[3] = 0x80 | (params.sav_eav_f << 6) |
-				(vact << 5) | (hact << 4) |
-				((hact ^ vact) << 3) |
-				((hact ^ params.sav_eav_f) << 2) |
-				((params.sav_eav_f ^ vact) << 1) |
-				(hact ^ vact ^ params.sav_eav_f);
-		}
+		tpg_fill_plane_extras(tpg, &params, p, h,
+				vbuf + buf_line * params.stride);
 	}
 }
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 25/29] vivid-tpg: split off the pattern drawing code.
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (23 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 24/29] vivid-tpg: move the 'extras' drawing to a separate function Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 26/29] vivid: add new format fields Hans Verkuil
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The last part of the vivid-tpg refactoring: split off the pattern
drawing code into a function of its own. This greatly improves the
readability and maintainability of this code.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-tpg.c | 320 ++++++++++++++++---------------
 1 file changed, 162 insertions(+), 158 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index 5ff9db9..e7086e1 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -1689,19 +1689,153 @@ static void tpg_fill_plane_extras(const struct tpg_data *tpg,
 	}
 }
 
-void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
+static void tpg_fill_plane_pattern(const struct tpg_data *tpg,
+				   const struct tpg_draw_params *params,
+				   unsigned p, unsigned h, u8 *vbuf)
+{
+	unsigned twopixsize = params->twopixsize;
+	unsigned img_width = params->img_width;
+	unsigned mv_hor_old = params->mv_hor_old;
+	unsigned mv_hor_new = params->mv_hor_new;
+	unsigned mv_vert_old = params->mv_vert_old;
+	unsigned mv_vert_new = params->mv_vert_new;
+	unsigned frame_line = params->frame_line;
+	unsigned frame_line_next = params->frame_line_next;
+	unsigned line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
+	bool even;
+	bool fill_blank = false;
+	unsigned pat_line_old;
+	unsigned pat_line_new;
+	u8 *linestart_older;
+	u8 *linestart_newer;
+	u8 *linestart_top;
+	u8 *linestart_bottom;
+
+	even = !(frame_line & 1);
+
+	if (h >= params->hmax) {
+		if (params->hmax == tpg->compose.height)
+			return;
+		if (!tpg->perc_fill_blank)
+			return;
+		fill_blank = true;
+	}
+
+	if (tpg->vflip) {
+		frame_line = tpg->src_height - frame_line - 1;
+		frame_line_next = tpg->src_height - frame_line_next - 1;
+	}
+
+	if (fill_blank) {
+		linestart_older = tpg->contrast_line[p];
+		linestart_newer = tpg->contrast_line[p];
+	} else if (tpg->qual != TPG_QUAL_NOISE &&
+		   (frame_line < tpg->border.top ||
+		    frame_line >= tpg->border.top + tpg->border.height)) {
+		linestart_older = tpg->black_line[p];
+		linestart_newer = tpg->black_line[p];
+	} else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
+		linestart_older = tpg->random_line[p] +
+				  twopixsize * prandom_u32_max(tpg->src_width / 2);
+		linestart_newer = tpg->random_line[p] +
+				  twopixsize * prandom_u32_max(tpg->src_width / 2);
+	} else {
+		unsigned frame_line_old =
+			(frame_line + mv_vert_old) % tpg->src_height;
+		unsigned frame_line_new =
+			(frame_line + mv_vert_new) % tpg->src_height;
+		unsigned pat_line_next_old;
+		unsigned pat_line_next_new;
+
+		pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
+		pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
+		linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
+		linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
+
+		if (tpg->vdownsampling[p] > 1 && frame_line != frame_line_next) {
+			int avg_pat;
+
+			/*
+			 * Now decide whether we need to use downsampled_lines[].
+			 * That's necessary if the two lines use different patterns.
+			 */
+			pat_line_next_old = tpg_get_pat_line(tpg,
+					(frame_line_next + mv_vert_old) % tpg->src_height);
+			pat_line_next_new = tpg_get_pat_line(tpg,
+					(frame_line_next + mv_vert_new) % tpg->src_height);
+
+			switch (tpg->field) {
+			case V4L2_FIELD_INTERLACED:
+			case V4L2_FIELD_INTERLACED_BT:
+			case V4L2_FIELD_INTERLACED_TB:
+				avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
+				if (avg_pat < 0)
+					break;
+				linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
+				linestart_newer = linestart_older;
+				break;
+			case V4L2_FIELD_NONE:
+			case V4L2_FIELD_TOP:
+			case V4L2_FIELD_BOTTOM:
+			case V4L2_FIELD_SEQ_BT:
+			case V4L2_FIELD_SEQ_TB:
+				avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
+				if (avg_pat >= 0)
+					linestart_older = tpg->downsampled_lines[avg_pat][p] +
+						mv_hor_old;
+				avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
+				if (avg_pat >= 0)
+					linestart_newer = tpg->downsampled_lines[avg_pat][p] +
+						mv_hor_new;
+				break;
+			}
+		}
+		linestart_older += line_offset;
+		linestart_newer += line_offset;
+	}
+	if (tpg->field_alternate) {
+		linestart_top = linestart_bottom = linestart_older;
+	} else if (params->is_60hz) {
+		linestart_top = linestart_newer;
+		linestart_bottom = linestart_older;
+	} else {
+		linestart_top = linestart_older;
+		linestart_bottom = linestart_newer;
+	}
+
+	switch (tpg->field) {
+	case V4L2_FIELD_INTERLACED:
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_SEQ_TB:
+	case V4L2_FIELD_SEQ_BT:
+		if (even)
+			memcpy(vbuf, linestart_top, img_width);
+		else
+			memcpy(vbuf, linestart_bottom, img_width);
+		break;
+	case V4L2_FIELD_INTERLACED_BT:
+		if (even)
+			memcpy(vbuf, linestart_bottom, img_width);
+		else
+			memcpy(vbuf, linestart_top, img_width);
+		break;
+	case V4L2_FIELD_TOP:
+		memcpy(vbuf, linestart_top, img_width);
+		break;
+	case V4L2_FIELD_BOTTOM:
+		memcpy(vbuf, linestart_bottom, img_width);
+		break;
+	case V4L2_FIELD_NONE:
+	default:
+		memcpy(vbuf, linestart_older, img_width);
+		break;
+	}
+}
+
+void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
+			   unsigned p, u8 *vbuf)
 {
 	struct tpg_draw_params params;
-	unsigned mv_hor_old;
-	unsigned mv_hor_new;
-	unsigned mv_vert_old;
-	unsigned mv_vert_new;
-	int h;
-	unsigned twopixsize;
-	unsigned vdiv = tpg->vdownsampling[p];
-	unsigned img_width;
-	unsigned line_offset;
-	unsigned stride;
 	unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
 
 	/* Coarse scaling with Bresenham */
@@ -1709,6 +1843,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height;
 	unsigned src_y = 0;
 	unsigned error = 0;
+	unsigned h;
 
 	tpg_recalc(tpg);
 
@@ -1720,37 +1855,15 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 	params.hmax = (tpg->compose.height * tpg->perc_fill) / 100;
 
 	tpg_fill_params_pattern(tpg, p, &params);
-
-	mv_hor_old = params.mv_hor_old;
-	mv_hor_new = params.mv_hor_new;
-	mv_vert_old = params.mv_vert_old;
-	mv_vert_new = params.mv_vert_new;
-
 	tpg_fill_params_extras(tpg, p, &params);
 
-	twopixsize = params.twopixsize;
-	img_width = params.img_width;
-	stride = params.stride;
-
 	vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
-	line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
 
 	for (h = 0; h < tpg->compose.height; h++) {
-		bool even;
-		bool fill_blank = false;
-		unsigned frame_line;
 		unsigned buf_line;
-		unsigned pat_line_old;
-		unsigned pat_line_new;
-		u8 *linestart_older;
-		u8 *linestart_newer;
-		u8 *linestart_top;
-		u8 *linestart_bottom;
 
 		params.frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
 		params.frame_line_next = params.frame_line;
-		frame_line = params.frame_line;
-		even = !(frame_line & 1);
 		buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
 		src_y += int_part;
 		error += fract_part;
@@ -1759,7 +1872,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			src_y++;
 		}
 
-		if (vdiv > 1) {
+		if (tpg->vdownsampling[p] > 1) {
 			/*
 			 * When doing vertical downsampling the field setting
 			 * matters: for SEQ_BT/TB we downsample each field
@@ -1770,135 +1883,26 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
 			 */
 			if (tpg->field == V4L2_FIELD_SEQ_BT ||
 			    tpg->field == V4L2_FIELD_SEQ_TB) {
+				unsigned next_src_y = src_y;
+
 				if ((h & 3) >= 2)
 					continue;
-			} else if (h & 1) {
-				continue;
-			}
-
-			buf_line /= vdiv;
-		}
-
-		if (h >= params.hmax) {
-			if (params.hmax == tpg->compose.height)
-				continue;
-			if (!tpg->perc_fill_blank)
-				continue;
-			fill_blank = true;
-		}
-
-		if (tpg->vflip)
-			frame_line = tpg->src_height - frame_line - 1;
-
-		if (fill_blank) {
-			linestart_older = tpg->contrast_line[p];
-			linestart_newer = tpg->contrast_line[p];
-		} else if (tpg->qual != TPG_QUAL_NOISE &&
-			   (frame_line < tpg->border.top ||
-			    frame_line >= tpg->border.top + tpg->border.height)) {
-			linestart_older = tpg->black_line[p];
-			linestart_newer = tpg->black_line[p];
-		} else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
-			linestart_older = tpg->random_line[p] +
-					  twopixsize * prandom_u32_max(tpg->src_width / 2);
-			linestart_newer = tpg->random_line[p] +
-					  twopixsize * prandom_u32_max(tpg->src_width / 2);
-		} else {
-			unsigned frame_line_old =
-				(frame_line + mv_vert_old) % tpg->src_height;
-			unsigned frame_line_new =
-				(frame_line + mv_vert_new) % tpg->src_height;
-			unsigned pat_line_next_old;
-			unsigned pat_line_next_new;
-
-			pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
-			pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
-			linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
-			linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
-
-			if (vdiv > 1) {
-				unsigned frame_line_next;
-				int avg_pat;
-
-				/*
-				 * Now decide whether we need to use downsampled_lines[].
-				 * That's necessary if the two lines use different patterns.
-				 */
-				frame_line_next = tpg_calc_frameline(tpg, src_y, tpg->field);
-				if (tpg->vflip)
-					frame_line_next = tpg->src_height - frame_line_next - 1;
-				pat_line_next_old = tpg_get_pat_line(tpg,
-						(frame_line_next + mv_vert_old) % tpg->src_height);
-				pat_line_next_new = tpg_get_pat_line(tpg,
-						(frame_line_next + mv_vert_new) % tpg->src_height);
-
-				switch (tpg->field) {
-				case V4L2_FIELD_INTERLACED:
-				case V4L2_FIELD_INTERLACED_BT:
-				case V4L2_FIELD_INTERLACED_TB:
-					avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
-					if (avg_pat < 0)
-						break;
-					linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
-					linestart_newer = linestart_older;
-					break;
-				case V4L2_FIELD_NONE:
-				case V4L2_FIELD_TOP:
-				case V4L2_FIELD_BOTTOM:
-				case V4L2_FIELD_SEQ_BT:
-				case V4L2_FIELD_SEQ_TB:
-					avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
-					if (avg_pat >= 0)
-						linestart_older = tpg->downsampled_lines[avg_pat][p] +
-							mv_hor_old;
-					avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
-					if (avg_pat >= 0)
-						linestart_newer = tpg->downsampled_lines[avg_pat][p] +
-							mv_hor_new;
-					break;
-				}
+				next_src_y += int_part;
+				if (error + fract_part >= tpg->compose.height)
+					next_src_y++;
+				params.frame_line_next =
+					tpg_calc_frameline(tpg, next_src_y, tpg->field);
+			} else {
+				if (h & 1)
+					continue;
+				params.frame_line_next =
+					tpg_calc_frameline(tpg, src_y, tpg->field);
 			}
-			linestart_older += line_offset;
-			linestart_newer += line_offset;
-		}
-		if (tpg->field_alternate) {
-			linestart_top = linestart_bottom = linestart_older;
-		} else if (params.is_60hz) {
-			linestart_top = linestart_newer;
-			linestart_bottom = linestart_older;
-		} else {
-			linestart_top = linestart_older;
-			linestart_bottom = linestart_newer;
-		}
 
-		switch (tpg->field) {
-		case V4L2_FIELD_INTERLACED:
-		case V4L2_FIELD_INTERLACED_TB:
-		case V4L2_FIELD_SEQ_TB:
-		case V4L2_FIELD_SEQ_BT:
-			if (even)
-				memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-			else
-				memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-			break;
-		case V4L2_FIELD_INTERLACED_BT:
-			if (even)
-				memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-			else
-				memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-			break;
-		case V4L2_FIELD_TOP:
-			memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-			break;
-		case V4L2_FIELD_BOTTOM:
-			memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-			break;
-		case V4L2_FIELD_NONE:
-		default:
-			memcpy(vbuf + buf_line * stride, linestart_older, img_width);
-			break;
+			buf_line /= tpg->vdownsampling[p];
 		}
-
+		tpg_fill_plane_pattern(tpg, &params, p, h,
+				vbuf + buf_line * params.stride);
 		tpg_fill_plane_extras(tpg, &params, p, h,
 				vbuf + buf_line * params.stride);
 	}
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 26/29] vivid: add new format fields
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (24 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 25/29] vivid-tpg: split off the pattern drawing code Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 27/29] vivid: add support for single buffer planar formats Hans Verkuil
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

These fields are necessary to handle the new planar formats.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-core.h       |  4 +-
 drivers/media/platform/vivid/vivid-vid-cap.c    | 18 ++++--
 drivers/media/platform/vivid/vivid-vid-common.c | 84 ++++++++++++++++++-------
 drivers/media/platform/vivid/vivid-vid-out.c    |  8 +--
 4 files changed, 81 insertions(+), 33 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 191d9b5..bcefd19 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -79,12 +79,14 @@ extern unsigned vivid_debug;
 struct vivid_fmt {
 	const char *name;
 	u32	fourcc;          /* v4l2 format id */
-	u8	depth;
 	bool	is_yuv;
 	bool	can_do_overlay;
+	u8	vdownsampling[TPG_MAX_PLANES];
 	u32	alpha_mask;
 	u8	planes;
+	u8	buffers;
 	u32	data_offset[TPG_MAX_PLANES];
+	u32	bit_depth[TPG_MAX_PLANES];
 };
 
 extern struct vivid_fmt vivid_formats[];
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index d41ac44..4d50961 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -42,20 +42,26 @@ static const struct vivid_fmt formats_ovl[] = {
 	{
 		.name     = "RGB565 (LE)",
 		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "XRGB555 (LE)",
 		.fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "ARGB555 (LE)",
 		.fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 };
 
@@ -597,9 +603,9 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
 	/* This driver supports custom bytesperline values */
 
 	/* Calculate the minimum supported bytesperline value */
-	bytesperline = (mp->width * fmt->depth) >> 3;
+	bytesperline = (mp->width * fmt->bit_depth[0]) >> 3;
 	/* Calculate the maximum supported bytesperline value */
-	max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->depth) >> 3;
+	max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3;
 	mp->num_planes = fmt->planes;
 	for (p = 0; p < mp->num_planes; p++) {
 		if (pfmt[p].bytesperline > max_bpl)
@@ -1224,7 +1230,7 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
 	fmt = vivid_get_format(dev, a->fmt.pixelformat);
 	if (!fmt || !fmt->can_do_overlay)
 		return -EINVAL;
-	if (a->fmt.bytesperline < (a->fmt.width * fmt->depth) / 8)
+	if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
 		return -EINVAL;
 	if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage)
 		return -EINVAL;
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 49c9bc6..7a02aef 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -46,139 +46,179 @@ struct vivid_fmt vivid_formats[] = {
 	{
 		.name     = "4:2:2, packed, YUYV",
 		.fourcc   = V4L2_PIX_FMT_YUYV,
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.is_yuv   = true,
 		.planes   = 1,
+		.buffers = 1,
 		.data_offset = { PLANE0_DATA_OFFSET, 0 },
 	},
 	{
 		.name     = "4:2:2, packed, UYVY",
 		.fourcc   = V4L2_PIX_FMT_UYVY,
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.is_yuv   = true,
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "4:2:2, packed, YVYU",
 		.fourcc   = V4L2_PIX_FMT_YVYU,
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.is_yuv   = true,
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "4:2:2, packed, VYUY",
 		.fourcc   = V4L2_PIX_FMT_VYUY,
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.is_yuv   = true,
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "RGB565 (LE)",
 		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 		.can_do_overlay = true,
 	},
 	{
 		.name     = "RGB565 (BE)",
 		.fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 		.can_do_overlay = true,
 	},
 	{
 		.name     = "RGB555 (LE)",
 		.fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 		.can_do_overlay = true,
 	},
 	{
 		.name     = "XRGB555 (LE)",
 		.fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 		.can_do_overlay = true,
 	},
 	{
 		.name     = "ARGB555 (LE)",
 		.fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 		.can_do_overlay = true,
 		.alpha_mask = 0x8000,
 	},
 	{
 		.name     = "RGB555 (BE)",
 		.fourcc   = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
-		.depth    = 16,
+		.vdownsampling = { 1 },
+		.bit_depth = { 16 },
 		.planes   = 1,
+		.buffers = 1,
 		.can_do_overlay = true,
 	},
 	{
 		.name     = "RGB24 (LE)",
 		.fourcc   = V4L2_PIX_FMT_RGB24, /* rgb */
-		.depth    = 24,
+		.vdownsampling = { 1 },
+		.bit_depth = { 24 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "RGB24 (BE)",
 		.fourcc   = V4L2_PIX_FMT_BGR24, /* bgr */
-		.depth    = 24,
+		.vdownsampling = { 1 },
+		.bit_depth = { 24 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "RGB32 (LE)",
 		.fourcc   = V4L2_PIX_FMT_RGB32, /* argb */
-		.depth    = 32,
+		.vdownsampling = { 1 },
+		.bit_depth = { 32 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "RGB32 (BE)",
 		.fourcc   = V4L2_PIX_FMT_BGR32, /* bgra */
-		.depth    = 32,
+		.vdownsampling = { 1 },
+		.bit_depth = { 32 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "XRGB32 (LE)",
 		.fourcc   = V4L2_PIX_FMT_XRGB32, /* argb */
-		.depth    = 32,
+		.vdownsampling = { 1 },
+		.bit_depth = { 32 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "XRGB32 (BE)",
 		.fourcc   = V4L2_PIX_FMT_XBGR32, /* bgra */
-		.depth    = 32,
+		.vdownsampling = { 1 },
+		.bit_depth = { 32 },
 		.planes   = 1,
+		.buffers = 1,
 	},
 	{
 		.name     = "ARGB32 (LE)",
 		.fourcc   = V4L2_PIX_FMT_ARGB32, /* argb */
-		.depth    = 32,
+		.vdownsampling = { 1 },
+		.bit_depth = { 32 },
 		.planes   = 1,
+		.buffers = 1,
 		.alpha_mask = 0x000000ff,
 	},
 	{
 		.name     = "ARGB32 (BE)",
 		.fourcc   = V4L2_PIX_FMT_ABGR32, /* bgra */
-		.depth    = 32,
+		.vdownsampling = { 1 },
+		.bit_depth = { 32 },
 		.planes   = 1,
+		.buffers = 1,
 		.alpha_mask = 0xff000000,
 	},
 	{
-		.name     = "4:2:2, planar, YUV",
+		.name     = "4:2:2, biplanar, YUV",
 		.fourcc   = V4L2_PIX_FMT_NV16M,
-		.depth    = 8,
+		.vdownsampling = { 1, 1 },
+		.bit_depth = { 8, 8 },
 		.is_yuv   = true,
 		.planes   = 2,
+		.buffers = 2,
 		.data_offset = { PLANE0_DATA_OFFSET, 0 },
 	},
 	{
-		.name     = "4:2:2, planar, YVU",
+		.name     = "4:2:2, biplanar, YVU",
 		.fourcc   = V4L2_PIX_FMT_NV61M,
-		.depth    = 8,
+		.vdownsampling = { 1, 1 },
+		.bit_depth = { 8, 8 },
 		.is_yuv   = true,
 		.planes   = 2,
+		.buffers = 2,
 		.data_offset = { 0, PLANE0_DATA_OFFSET },
 	},
 };
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 39ff79f..17b026b 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -267,9 +267,9 @@ void vivid_update_format_out(struct vivid_dev *dev)
 	if (V4L2_FIELD_HAS_T_OR_B(dev->field_out))
 		dev->crop_out.height /= 2;
 	dev->fmt_out_rect = dev->crop_out;
-	dev->bytesperline_out[0] = (dev->sink_rect.width * dev->fmt_out->depth) / 8;
+	dev->bytesperline_out[0] = (dev->sink_rect.width * dev->fmt_out->bit_depth[0]) / 8;
 	if (dev->fmt_out->planes == 2)
-		dev->bytesperline_out[1] = (dev->sink_rect.width * dev->fmt_out->depth) / 8;
+		dev->bytesperline_out[1] = (dev->sink_rect.width * dev->fmt_out->bit_depth[0]) / 8;
 }
 
 /* Map the field to something that is valid for the current output */
@@ -386,9 +386,9 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
 	/* This driver supports custom bytesperline values */
 
 	/* Calculate the minimum supported bytesperline value */
-	bytesperline = (mp->width * fmt->depth) >> 3;
+	bytesperline = (mp->width * fmt->bit_depth[0]) >> 3;
 	/* Calculate the maximum supported bytesperline value */
-	max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->depth) >> 3;
+	max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3;
 	mp->num_planes = fmt->planes;
 	for (p = 0; p < mp->num_planes; p++) {
 		if (pfmt[p].bytesperline > max_bpl)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 27/29] vivid: add support for single buffer planar formats
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (25 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 26/29] vivid: add new format fields Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 28/29] vivid: add downsampling support Hans Verkuil
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Make vivid aware of the difference of planes and buffers. Note that
this does not yet add support for hor/vert downsampled formats.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-core.h        |  2 +-
 drivers/media/platform/vivid/vivid-kthread-cap.c | 54 ++++++++++++------
 drivers/media/platform/vivid/vivid-vid-cap.c     | 58 ++++++++++----------
 drivers/media/platform/vivid/vivid-vid-common.c  |  2 +-
 drivers/media/platform/vivid/vivid-vid-out.c     | 70 ++++++++++++++----------
 5 files changed, 106 insertions(+), 80 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index bcefd19..9e15aee 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -334,7 +334,7 @@ struct vivid_dev {
 	u32				ycbcr_enc_out;
 	u32				quantization_out;
 	u32				service_set_out;
-	u32				bytesperline_out[TPG_MAX_PLANES];
+	unsigned			bytesperline_out[TPG_MAX_PLANES];
 	unsigned			tv_field_out;
 	unsigned			tv_audio_output;
 	bool				vbi_out_have_wss;
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 9976d45..22e1784 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -229,6 +229,20 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev)
 		dev->loop_vid_overlay_cap.left, dev->loop_vid_overlay_cap.top);
 }
 
+static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf,
+			 unsigned p, unsigned bpl[TPG_MAX_PLANES], unsigned h)
+{
+	unsigned i;
+	void *vbuf;
+
+	if (p == 0 || tpg_g_buffers(tpg) > 1)
+		return vb2_plane_vaddr(&buf->vb, p);
+	vbuf = vb2_plane_vaddr(&buf->vb, 0);
+	for (i = 0; i < p; i++)
+		vbuf += bpl[i] * h / tpg->vdownsampling[i];
+	return vbuf;
+}
+
 static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 		struct vivid_buffer *vid_cap_buf)
 {
@@ -269,8 +283,10 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 
 	vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field;
 
-	voutbuf = vb2_plane_vaddr(&vid_out_buf->vb, p) +
-				  vid_out_buf->vb.v4l2_planes[p].data_offset;
+	voutbuf = plane_vaddr(tpg, vid_out_buf, p,
+			      dev->bytesperline_out, dev->fmt_out_rect.height);
+	if (p < dev->fmt_out->buffers)
+		voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset;
 	voutbuf += dev->loop_vid_out.left * pixsize + dev->loop_vid_out.top * stride_out;
 	vcapbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride_cap;
 
@@ -395,6 +411,7 @@ update_vid_out_y:
 
 static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
+	struct tpg_data *tpg = &dev->tpg;
 	unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
 	unsigned line_height = 16 / factor;
 	bool is_tv = vivid_is_sdtv_cap(dev);
@@ -436,28 +453,29 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 	} else {
 		buf->vb.v4l2_buf.field = dev->field_cap;
 	}
-	tpg_s_field(&dev->tpg, buf->vb.v4l2_buf.field,
+	tpg_s_field(tpg, buf->vb.v4l2_buf.field,
 		    dev->field_cap == V4L2_FIELD_ALTERNATE);
-	tpg_s_perc_fill_blank(&dev->tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
+	tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
 
 	vivid_precalc_copy_rects(dev);
 
-	for (p = 0; p < tpg_g_planes(&dev->tpg); p++) {
-		void *vbuf = vb2_plane_vaddr(&buf->vb, p);
+	for (p = 0; p < tpg_g_planes(tpg); p++) {
+		void *vbuf = plane_vaddr(tpg, buf, p,
+					 tpg->bytesperline, tpg->buf_height);
 
 		/*
 		 * The first plane of a multiplanar format has a non-zero
 		 * data_offset. This helps testing whether the application
 		 * correctly supports non-zero data offsets.
 		 */
-		if (dev->fmt_cap->data_offset[p]) {
+		if (p < tpg_g_buffers(tpg) && dev->fmt_cap->data_offset[p]) {
 			memset(vbuf, dev->fmt_cap->data_offset[p] & 0xff,
 			       dev->fmt_cap->data_offset[p]);
 			vbuf += dev->fmt_cap->data_offset[p];
 		}
-		tpg_calc_text_basep(&dev->tpg, basep, p, vbuf);
+		tpg_calc_text_basep(tpg, basep, p, vbuf);
 		if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf))
-			tpg_fillbuffer(&dev->tpg, vivid_get_std_cap(dev), p, vbuf);
+			tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), p, vbuf);
 	}
 	dev->must_blank[buf->vb.v4l2_buf.index] = false;
 
@@ -476,12 +494,12 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 				(dev->field_cap == V4L2_FIELD_ALTERNATE) ?
 					(buf->vb.v4l2_buf.field == V4L2_FIELD_TOP ?
 					 " top" : " bottom") : "");
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 	}
 	if (dev->osd_mode == 0) {
 		snprintf(str, sizeof(str), " %dx%d, input %d ",
 				dev->src_rect.width, dev->src_rect.height, dev->input);
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 
 		gain = v4l2_ctrl_g_ctrl(dev->gain);
 		mutex_lock(dev->ctrl_hdl_user_vid.lock);
@@ -491,38 +509,38 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 			dev->contrast->cur.val,
 			dev->saturation->cur.val,
 			dev->hue->cur.val);
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 		snprintf(str, sizeof(str),
 			" autogain %d, gain %3d, alpha 0x%02x ",
 			dev->autogain->cur.val, gain, dev->alpha->cur.val);
 		mutex_unlock(dev->ctrl_hdl_user_vid.lock);
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 		mutex_lock(dev->ctrl_hdl_user_aud.lock);
 		snprintf(str, sizeof(str),
 			" volume %3d, mute %d ",
 			dev->volume->cur.val, dev->mute->cur.val);
 		mutex_unlock(dev->ctrl_hdl_user_aud.lock);
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 		mutex_lock(dev->ctrl_hdl_user_gen.lock);
 		snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
 			dev->int32->cur.val,
 			*dev->int64->p_cur.p_s64,
 			dev->bitmask->cur.val);
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 		snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
 			dev->boolean->cur.val,
 			dev->menu->qmenu[dev->menu->cur.val],
 			dev->string->p_cur.p_char);
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 		snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
 			dev->int_menu->qmenu_int[dev->int_menu->cur.val],
 			dev->int_menu->cur.val);
 		mutex_unlock(dev->ctrl_hdl_user_gen.lock);
-		tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 		if (dev->button_pressed) {
 			dev->button_pressed--;
 			snprintf(str, sizeof(str), " button pressed!");
-			tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+			tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 		}
 	}
 
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 4d50961..1d9ea2d 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -100,7 +100,7 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
 		       unsigned sizes[], void *alloc_ctxs[])
 {
 	struct vivid_dev *dev = vb2_get_drv_priv(vq);
-	unsigned planes = tpg_g_planes(&dev->tpg);
+	unsigned buffers = tpg_g_buffers(&dev->tpg);
 	unsigned h = dev->fmt_cap_rect.height;
 	unsigned p;
 
@@ -133,39 +133,36 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
 		mp = &fmt->fmt.pix_mp;
 		/*
 		 * Check if the number of planes in the specified format match
-		 * the number of planes in the current format. You can't mix that.
+		 * the number of buffers in the current format. You can't mix that.
 		 */
-		if (mp->num_planes != planes)
+		if (mp->num_planes != buffers)
 			return -EINVAL;
 		vfmt = vivid_get_format(dev, mp->pixelformat);
-		for (p = 0; p < planes; p++) {
+		for (p = 0; p < buffers; p++) {
 			sizes[p] = mp->plane_fmt[p].sizeimage;
-			if (sizes[0] < tpg_g_bytesperline(&dev->tpg, 0) * h +
+			if (sizes[p] < tpg_g_line_width(&dev->tpg, p) * h +
 							vfmt->data_offset[p])
 				return -EINVAL;
 		}
 	} else {
-		for (p = 0; p < planes; p++)
-			sizes[p] = tpg_g_bytesperline(&dev->tpg, p) * h +
+		for (p = 0; p < buffers; p++)
+			sizes[p] = tpg_g_line_width(&dev->tpg, p) * h +
 					dev->fmt_cap->data_offset[p];
 	}
 
 	if (vq->num_buffers + *nbuffers < 2)
 		*nbuffers = 2 - vq->num_buffers;
 
-	*nplanes = planes;
+	*nplanes = buffers;
 
 	/*
 	 * videobuf2-vmalloc allocator is context-less so no need to set
 	 * alloc_ctxs array.
 	 */
 
-	if (planes == 2)
-		dprintk(dev, 1, "%s, count=%d, sizes=%u, %u\n", __func__,
-			*nbuffers, sizes[0], sizes[1]);
-	else
-		dprintk(dev, 1, "%s, count=%d, size=%u\n", __func__,
-			*nbuffers, sizes[0]);
+	dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
+	for (p = 0; p < buffers; p++)
+		dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
 
 	return 0;
 }
@@ -174,7 +171,7 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
 {
 	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	unsigned long size;
-	unsigned planes = tpg_g_planes(&dev->tpg);
+	unsigned buffers = tpg_g_buffers(&dev->tpg);
 	unsigned p;
 
 	dprintk(dev, 1, "%s\n", __func__);
@@ -190,8 +187,8 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
 		dev->buf_prepare_error = false;
 		return -EINVAL;
 	}
-	for (p = 0; p < planes; p++) {
-		size = tpg_g_bytesperline(&dev->tpg, p) * dev->fmt_cap_rect.height +
+	for (p = 0; p < buffers; p++) {
+		size = tpg_g_line_width(&dev->tpg, p) * dev->fmt_cap_rect.height +
 			dev->fmt_cap->data_offset[p];
 
 		if (vb2_plane_size(vb, p) < size) {
@@ -532,11 +529,11 @@ int vivid_g_fmt_vid_cap(struct file *file, void *priv,
 	mp->colorspace   = vivid_colorspace_cap(dev);
 	mp->ycbcr_enc    = vivid_ycbcr_enc_cap(dev);
 	mp->quantization = vivid_quantization_cap(dev);
-	mp->num_planes = dev->fmt_cap->planes;
+	mp->num_planes = dev->fmt_cap->buffers;
 	for (p = 0; p < mp->num_planes; p++) {
 		mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p);
 		mp->plane_fmt[p].sizeimage =
-			mp->plane_fmt[p].bytesperline * mp->height +
+			tpg_g_line_width(&dev->tpg, p) * mp->height +
 			dev->fmt_cap->data_offset[p];
 	}
 	return 0;
@@ -602,18 +599,19 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
 
 	/* This driver supports custom bytesperline values */
 
-	/* Calculate the minimum supported bytesperline value */
-	bytesperline = (mp->width * fmt->bit_depth[0]) >> 3;
-	/* Calculate the maximum supported bytesperline value */
-	max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3;
-	mp->num_planes = fmt->planes;
+	mp->num_planes = fmt->buffers;
 	for (p = 0; p < mp->num_planes; p++) {
+		/* Calculate the minimum supported bytesperline value */
+		bytesperline = (mp->width * fmt->bit_depth[p]) >> 3;
+		/* Calculate the maximum supported bytesperline value */
+		max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[p]) >> 3;
+
 		if (pfmt[p].bytesperline > max_bpl)
 			pfmt[p].bytesperline = max_bpl;
 		if (pfmt[p].bytesperline < bytesperline)
 			pfmt[p].bytesperline = bytesperline;
-		pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height +
-			fmt->data_offset[p];
+		pfmt[p].sizeimage = tpg_calc_line_width(&dev->tpg, p, pfmt[p].bytesperline) *
+			mp->height + fmt->data_offset[p];
 		memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
 	}
 	mp->colorspace = vivid_colorspace_cap(dev);
@@ -633,6 +631,7 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
 	struct vb2_queue *q = &dev->vb_vid_cap_q;
 	int ret = vivid_try_fmt_vid_cap(file, priv, f);
 	unsigned factor = 1;
+	unsigned p;
 	unsigned i;
 
 	if (ret < 0)
@@ -735,16 +734,15 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
 	dev->fmt_cap_rect.width = mp->width;
 	dev->fmt_cap_rect.height = mp->height;
 	tpg_s_buf_height(&dev->tpg, mp->height);
-	tpg_s_bytesperline(&dev->tpg, 0, mp->plane_fmt[0].bytesperline);
-	if (tpg_g_planes(&dev->tpg) > 1)
-		tpg_s_bytesperline(&dev->tpg, 1, mp->plane_fmt[1].bytesperline);
+	tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
+	for (p = 0; p < tpg_g_buffers(&dev->tpg); p++)
+		tpg_s_bytesperline(&dev->tpg, p, mp->plane_fmt[p].bytesperline);
 	dev->field_cap = mp->field;
 	if (dev->field_cap == V4L2_FIELD_ALTERNATE)
 		tpg_s_field(&dev->tpg, V4L2_FIELD_TOP, true);
 	else
 		tpg_s_field(&dev->tpg, dev->field_cap, false);
 	tpg_s_crop_compose(&dev->tpg, &dev->crop_cap, &dev->compose_cap);
-	tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
 	if (vivid_is_sdtv_cap(dev))
 		dev->tv_field_cap = mp->field;
 	tpg_update_mv_step(&dev->tpg);
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 7a02aef..0f93fea 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -234,7 +234,7 @@ const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
 	for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
 		fmt = &vivid_formats[k];
 		if (fmt->fourcc == pixelformat)
-			if (fmt->planes == 1 || dev->multiplanar)
+			if (fmt->buffers == 1 || dev->multiplanar)
 				return fmt;
 	}
 
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 17b026b..69fd382 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -36,9 +36,14 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
 		       unsigned sizes[], void *alloc_ctxs[])
 {
 	struct vivid_dev *dev = vb2_get_drv_priv(vq);
-	unsigned planes = dev->fmt_out->planes;
+	const struct vivid_fmt *vfmt = dev->fmt_out;
+	unsigned planes = vfmt->buffers;
 	unsigned h = dev->fmt_out_rect.height;
 	unsigned size = dev->bytesperline_out[0] * h;
+	unsigned p;
+
+	for (p = vfmt->buffers; p < vfmt->planes; p++)
+		size += dev->bytesperline_out[p] * h;
 
 	if (dev->field_out == V4L2_FIELD_ALTERNATE) {
 		/*
@@ -74,21 +79,16 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
 		if (mp->num_planes != planes)
 			return -EINVAL;
 		sizes[0] = mp->plane_fmt[0].sizeimage;
-		if (planes == 2) {
-			sizes[1] = mp->plane_fmt[1].sizeimage;
-			if (sizes[0] < dev->bytesperline_out[0] * h ||
-			    sizes[1] < dev->bytesperline_out[1] * h)
-				return -EINVAL;
-		} else if (sizes[0] < size) {
+		if (sizes[0] < size)
 			return -EINVAL;
+		for (p = 1; p < planes; p++) {
+			sizes[p] = mp->plane_fmt[p].sizeimage;
+			if (sizes[p] < dev->bytesperline_out[p] * h)
+				return -EINVAL;
 		}
 	} else {
-		if (planes == 2) {
-			sizes[0] = dev->bytesperline_out[0] * h;
-			sizes[1] = dev->bytesperline_out[1] * h;
-		} else {
-			sizes[0] = size;
-		}
+		for (p = 0; p < planes; p++)
+			sizes[p] = p ? dev->bytesperline_out[p] * h : size;
 	}
 
 	if (vq->num_buffers + *nbuffers < 2)
@@ -101,12 +101,9 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
 	 * alloc_ctxs array.
 	 */
 
-	if (planes == 2)
-		dprintk(dev, 1, "%s, count=%d, sizes=%u, %u\n", __func__,
-			*nbuffers, sizes[0], sizes[1]);
-	else
-		dprintk(dev, 1, "%s, count=%d, size=%u\n", __func__,
-			*nbuffers, sizes[0]);
+	dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
+	for (p = 0; p < planes; p++)
+		dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
 	return 0;
 }
 
@@ -114,7 +111,7 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb)
 {
 	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	unsigned long size;
-	unsigned planes = dev->fmt_out->planes;
+	unsigned planes = dev->fmt_out->buffers;
 	unsigned p;
 
 	dprintk(dev, 1, "%s\n", __func__);
@@ -220,7 +217,7 @@ const struct vb2_ops vivid_vid_out_qops = {
 void vivid_update_format_out(struct vivid_dev *dev)
 {
 	struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
-	unsigned size;
+	unsigned size, p;
 
 	switch (dev->output_type[dev->output]) {
 	case SVID:
@@ -267,9 +264,9 @@ void vivid_update_format_out(struct vivid_dev *dev)
 	if (V4L2_FIELD_HAS_T_OR_B(dev->field_out))
 		dev->crop_out.height /= 2;
 	dev->fmt_out_rect = dev->crop_out;
-	dev->bytesperline_out[0] = (dev->sink_rect.width * dev->fmt_out->bit_depth[0]) / 8;
-	if (dev->fmt_out->planes == 2)
-		dev->bytesperline_out[1] = (dev->sink_rect.width * dev->fmt_out->bit_depth[0]) / 8;
+	for (p = 0; p < dev->fmt_out->planes; p++)
+		dev->bytesperline_out[p] =
+			(dev->sink_rect.width * dev->fmt_out->bit_depth[p]) / 8;
 }
 
 /* Map the field to something that is valid for the current output */
@@ -313,21 +310,27 @@ int vivid_g_fmt_vid_out(struct file *file, void *priv,
 {
 	struct vivid_dev *dev = video_drvdata(file);
 	struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
+	const struct vivid_fmt *fmt = dev->fmt_out;
 	unsigned p;
 
 	mp->width        = dev->fmt_out_rect.width;
 	mp->height       = dev->fmt_out_rect.height;
 	mp->field        = dev->field_out;
-	mp->pixelformat  = dev->fmt_out->fourcc;
+	mp->pixelformat  = fmt->fourcc;
 	mp->colorspace   = dev->colorspace_out;
 	mp->ycbcr_enc    = dev->ycbcr_enc_out;
 	mp->quantization = dev->quantization_out;
-	mp->num_planes = dev->fmt_out->planes;
+	mp->num_planes = fmt->buffers;
 	for (p = 0; p < mp->num_planes; p++) {
 		mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p];
 		mp->plane_fmt[p].sizeimage =
 			mp->plane_fmt[p].bytesperline * mp->height;
 	}
+	for (p = fmt->buffers; p < fmt->planes; p++) {
+		unsigned stride = dev->bytesperline_out[p];
+
+		mp->plane_fmt[0].sizeimage += stride * mp->height;
+	}
 	return 0;
 }
 
@@ -389,7 +392,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
 	bytesperline = (mp->width * fmt->bit_depth[0]) >> 3;
 	/* Calculate the maximum supported bytesperline value */
 	max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3;
-	mp->num_planes = fmt->planes;
+	mp->num_planes = fmt->buffers;
 	for (p = 0; p < mp->num_planes; p++) {
 		if (pfmt[p].bytesperline > max_bpl)
 			pfmt[p].bytesperline = max_bpl;
@@ -398,6 +401,9 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
 		pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height;
 		memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
 	}
+	for (p = fmt->buffers; p < fmt->planes; p++)
+		pfmt[0].sizeimage += (pfmt[0].bytesperline * fmt->bit_depth[p]) /
+				     fmt->bit_depth[0];
 	mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 	mp->quantization = V4L2_QUANTIZATION_DEFAULT;
 	if (vivid_is_svid_out(dev)) {
@@ -429,6 +435,7 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
 	struct vb2_queue *q = &dev->vb_vid_out_q;
 	int ret = vivid_try_fmt_vid_out(file, priv, f);
 	unsigned factor = 1;
+	unsigned p;
 
 	if (ret < 0)
 		return ret;
@@ -524,9 +531,12 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
 
 	dev->fmt_out_rect.width = mp->width;
 	dev->fmt_out_rect.height = mp->height;
-	dev->bytesperline_out[0] = mp->plane_fmt[0].bytesperline;
-	if (mp->num_planes > 1)
-		dev->bytesperline_out[1] = mp->plane_fmt[1].bytesperline;
+	for (p = 0; p < mp->num_planes; p++)
+		dev->bytesperline_out[p] = mp->plane_fmt[p].bytesperline;
+	for (p = dev->fmt_out->buffers; p < dev->fmt_out->planes; p++)
+		dev->bytesperline_out[p] =
+			(dev->bytesperline_out[0] * dev->fmt_out->bit_depth[p]) /
+			dev->fmt_out->bit_depth[0];
 	dev->field_out = mp->field;
 	if (vivid_is_svid_out(dev))
 		dev->tv_field_out = mp->field;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 28/29] vivid: add downsampling support
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (26 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 27/29] vivid: add support for single buffer planar formats Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 15:44 ` [PATCH 29/29] vivid: add the new planar and monochrome formats Hans Verkuil
  2015-03-09 16:07 ` [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add support in vivid for downsampling. Most of the changes are in
vivid_copy_buffer which needs to know about the right line widths.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-kthread-cap.c | 68 ++++++++++++++----------
 drivers/media/platform/vivid/vivid-vid-out.c     |  7 +--
 2 files changed, 43 insertions(+), 32 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 22e1784..1727f54 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -249,8 +249,9 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 	bool blank = dev->must_blank[vid_cap_buf->vb.v4l2_buf.index];
 	struct tpg_data *tpg = &dev->tpg;
 	struct vivid_buffer *vid_out_buf = NULL;
-	unsigned pixsize = tpg_g_twopixelsize(tpg, p) / 2;
-	unsigned img_width = dev->compose_cap.width;
+	unsigned vdiv = dev->fmt_out->vdownsampling[p];
+	unsigned twopixsize = tpg_g_twopixelsize(tpg, p);
+	unsigned img_width = tpg_hdiv(tpg, p, dev->compose_cap.width);
 	unsigned img_height = dev->compose_cap.height;
 	unsigned stride_cap = tpg->bytesperline[p];
 	unsigned stride_out = dev->bytesperline_out[p];
@@ -269,6 +270,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 	unsigned vid_overlay_fract_part = 0;
 	unsigned vid_overlay_y = 0;
 	unsigned vid_overlay_error = 0;
+	unsigned vid_cap_left = tpg_hdiv(tpg, p, dev->loop_vid_cap.left);
 	unsigned vid_cap_right;
 	bool quick;
 
@@ -287,23 +289,25 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 			      dev->bytesperline_out, dev->fmt_out_rect.height);
 	if (p < dev->fmt_out->buffers)
 		voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset;
-	voutbuf += dev->loop_vid_out.left * pixsize + dev->loop_vid_out.top * stride_out;
-	vcapbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride_cap;
+	voutbuf += tpg_hdiv(tpg, p, dev->loop_vid_out.left) +
+		(dev->loop_vid_out.top / vdiv) * stride_out;
+	vcapbuf += tpg_hdiv(tpg, p, dev->compose_cap.left) +
+		(dev->compose_cap.top / vdiv) * stride_cap;
 
 	if (dev->loop_vid_copy.width == 0 || dev->loop_vid_copy.height == 0) {
 		/*
 		 * If there is nothing to copy, then just fill the capture window
 		 * with black.
 		 */
-		for (y = 0; y < hmax; y++, vcapbuf += stride_cap)
-			memcpy(vcapbuf, tpg->black_line[p], img_width * pixsize);
+		for (y = 0; y < hmax / vdiv; y++, vcapbuf += stride_cap)
+			memcpy(vcapbuf, tpg->black_line[p], img_width);
 		return 0;
 	}
 
 	if (dev->overlay_out_enabled &&
 	    dev->loop_vid_overlay.width && dev->loop_vid_overlay.height) {
 		vosdbuf = dev->video_vbase;
-		vosdbuf += dev->loop_fb_copy.left * pixsize +
+		vosdbuf += (dev->loop_fb_copy.left * twopixsize) / 2 +
 			   dev->loop_fb_copy.top * stride_osd;
 		vid_overlay_int_part = dev->loop_vid_overlay.height /
 				       dev->loop_vid_overlay_cap.height;
@@ -311,12 +315,12 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 					 dev->loop_vid_overlay_cap.height;
 	}
 
-	vid_cap_right = dev->loop_vid_cap.left + dev->loop_vid_cap.width;
+	vid_cap_right = tpg_hdiv(tpg, p, dev->loop_vid_cap.left + dev->loop_vid_cap.width);
 	/* quick is true if no video scaling is needed */
 	quick = dev->loop_vid_out.width == dev->loop_vid_cap.width;
 
 	dev->cur_scaled_line = dev->loop_vid_out.height;
-	for (y = 0; y < hmax; y++, vcapbuf += stride_cap) {
+	for (y = 0; y < hmax; y += vdiv, vcapbuf += stride_cap) {
 		/* osdline is true if this line requires overlay blending */
 		bool osdline = vosdbuf && y >= dev->loop_vid_overlay_cap.top &&
 			  y < dev->loop_vid_overlay_cap.top + dev->loop_vid_overlay_cap.height;
@@ -327,34 +331,34 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 		 */
 		if (y < dev->loop_vid_cap.top ||
 		    y >= dev->loop_vid_cap.top + dev->loop_vid_cap.height) {
-			memcpy(vcapbuf, tpg->black_line[p], img_width * pixsize);
+			memcpy(vcapbuf, tpg->black_line[p], img_width);
 			continue;
 		}
 
 		/* fill the left border with black */
 		if (dev->loop_vid_cap.left)
-			memcpy(vcapbuf, tpg->black_line[p], dev->loop_vid_cap.left * pixsize);
+			memcpy(vcapbuf, tpg->black_line[p], vid_cap_left);
 
 		/* fill the right border with black */
 		if (vid_cap_right < img_width)
-			memcpy(vcapbuf + vid_cap_right * pixsize,
-				tpg->black_line[p], (img_width - vid_cap_right) * pixsize);
+			memcpy(vcapbuf + vid_cap_right, tpg->black_line[p],
+				img_width - vid_cap_right);
 
 		if (quick && !osdline) {
-			memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize,
+			memcpy(vcapbuf + vid_cap_left,
 			       voutbuf + vid_out_y * stride_out,
-			       dev->loop_vid_cap.width * pixsize);
+			       tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
 			goto update_vid_out_y;
 		}
 		if (dev->cur_scaled_line == vid_out_y) {
-			memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize,
-			       dev->scaled_line,
-			       dev->loop_vid_cap.width * pixsize);
+			memcpy(vcapbuf + vid_cap_left, dev->scaled_line,
+			       tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
 			goto update_vid_out_y;
 		}
 		if (!osdline) {
 			scale_line(voutbuf + vid_out_y * stride_out, dev->scaled_line,
-				dev->loop_vid_out.width, dev->loop_vid_cap.width,
+				tpg_hdiv(tpg, p, dev->loop_vid_out.width),
+				tpg_hdiv(tpg, p, dev->loop_vid_cap.width),
 				tpg_g_twopixelsize(tpg, p));
 		} else {
 			/*
@@ -362,7 +366,8 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 			 * loop_vid_overlay rectangle.
 			 */
 			unsigned offset =
-				(dev->loop_vid_overlay.left - dev->loop_vid_copy.left) * pixsize;
+				((dev->loop_vid_overlay.left - dev->loop_vid_copy.left) *
+				 twopixsize) / 2;
 			u8 *osd = vosdbuf + vid_overlay_y * stride_osd;
 
 			scale_line(voutbuf + vid_out_y * stride_out, dev->blended_line,
@@ -372,18 +377,17 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 				blend_line(dev, vid_overlay_y + dev->loop_vid_overlay.top,
 					   dev->loop_vid_overlay.left,
 					   dev->blended_line + offset, osd,
-					   dev->loop_vid_overlay.width, pixsize);
+					   dev->loop_vid_overlay.width, twopixsize / 2);
 			else
 				memcpy(dev->blended_line + offset,
-				       osd, dev->loop_vid_overlay.width * pixsize);
+				       osd, (dev->loop_vid_overlay.width * twopixsize) / 2);
 			scale_line(dev->blended_line, dev->scaled_line,
 					dev->loop_vid_copy.width, dev->loop_vid_cap.width,
 					tpg_g_twopixelsize(tpg, p));
 		}
 		dev->cur_scaled_line = vid_out_y;
-		memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize,
-		       dev->scaled_line,
-		       dev->loop_vid_cap.width * pixsize);
+		memcpy(vcapbuf + vid_cap_left, dev->scaled_line,
+		       tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
 
 update_vid_out_y:
 		if (osdline) {
@@ -396,16 +400,16 @@ update_vid_out_y:
 		}
 		vid_out_y += vid_out_int_part;
 		vid_out_error += vid_out_fract_part;
-		if (vid_out_error >= dev->loop_vid_cap.height) {
-			vid_out_error -= dev->loop_vid_cap.height;
+		if (vid_out_error >= dev->loop_vid_cap.height / vdiv) {
+			vid_out_error -= dev->loop_vid_cap.height / vdiv;
 			vid_out_y++;
 		}
 	}
 
 	if (!blank)
 		return 0;
-	for (; y < img_height; y++, vcapbuf += stride_cap)
-		memcpy(vcapbuf, tpg->contrast_line[p], img_width * pixsize);
+	for (; y < img_height; y += vdiv, vcapbuf += stride_cap)
+		memcpy(vcapbuf, tpg->contrast_line[p], img_width);
 	return 0;
 }
 
@@ -604,6 +608,12 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
 	bool quick = dev->bitmap_cap == NULL && dev->clipcount_cap == 0;
 	int x, y, w, out_x = 0;
 
+	/*
+	 * Overlay support is only supported for formats that have a twopixelsize
+	 * that's >= 2. Warn and bail out if that's not the case.
+	 */
+	if (WARN_ON(pixsize == 0))
+		return;
 	if ((dev->overlay_cap_field == V4L2_FIELD_TOP ||
 	     dev->overlay_cap_field == V4L2_FIELD_BOTTOM) &&
 	    dev->overlay_cap_field != buf->vb.v4l2_buf.field)
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 69fd382..917cc69 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -43,7 +43,7 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
 	unsigned p;
 
 	for (p = vfmt->buffers; p < vfmt->planes; p++)
-		size += dev->bytesperline_out[p] * h;
+		size += dev->bytesperline_out[p] * h / vfmt->vdownsampling[p];
 
 	if (dev->field_out == V4L2_FIELD_ALTERNATE) {
 		/*
@@ -329,7 +329,8 @@ int vivid_g_fmt_vid_out(struct file *file, void *priv,
 	for (p = fmt->buffers; p < fmt->planes; p++) {
 		unsigned stride = dev->bytesperline_out[p];
 
-		mp->plane_fmt[0].sizeimage += stride * mp->height;
+		mp->plane_fmt[0].sizeimage +=
+			(stride * mp->height) / fmt->vdownsampling[p];
 	}
 	return 0;
 }
@@ -403,7 +404,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
 	}
 	for (p = fmt->buffers; p < fmt->planes; p++)
 		pfmt[0].sizeimage += (pfmt[0].bytesperline * fmt->bit_depth[p]) /
-				     fmt->bit_depth[0];
+				     (fmt->bit_depth[0] * fmt->vdownsampling[p]);
 	mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 	mp->quantization = V4L2_QUANTIZATION_DEFAULT;
 	if (vivid_is_svid_out(dev)) {
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 29/29] vivid: add the new planar and monochrome formats
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (27 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 28/29] vivid: add downsampling support Hans Verkuil
@ 2015-03-09 15:44 ` Hans Verkuil
  2015-03-09 16:07 ` [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 15:44 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Everything is in place to support these formats, so add them to
the list.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-vid-common.c | 114 +++++++++++++++++++++++-
 1 file changed, 111 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 0f93fea..7cb4aa0 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -51,7 +51,7 @@ struct vivid_fmt vivid_formats[] = {
 		.is_yuv   = true,
 		.planes   = 1,
 		.buffers = 1,
-		.data_offset = { PLANE0_DATA_OFFSET, 0 },
+		.data_offset = { PLANE0_DATA_OFFSET },
 	},
 	{
 		.name     = "4:2:2, packed, UYVY",
@@ -81,6 +81,78 @@ struct vivid_fmt vivid_formats[] = {
 		.buffers = 1,
 	},
 	{
+		.name     = "YUV 4:2:2 triplanar",
+		.fourcc   = V4L2_PIX_FMT_YUV422P,
+		.vdownsampling = { 1, 1, 1 },
+		.bit_depth = { 8, 4, 4 },
+		.is_yuv   = true,
+		.planes   = 3,
+		.buffers = 1,
+	},
+	{
+		.name     = "YUV 4:2:0 triplanar",
+		.fourcc   = V4L2_PIX_FMT_YUV420,
+		.vdownsampling = { 1, 2, 2 },
+		.bit_depth = { 8, 4, 4 },
+		.is_yuv   = true,
+		.planes   = 3,
+		.buffers = 1,
+	},
+	{
+		.name     = "YVU 4:2:0 triplanar",
+		.fourcc   = V4L2_PIX_FMT_YVU420,
+		.vdownsampling = { 1, 2, 2 },
+		.bit_depth = { 8, 4, 4 },
+		.is_yuv   = true,
+		.planes   = 3,
+		.buffers = 1,
+	},
+	{
+		.name     = "YUV 4:2:0 biplanar",
+		.fourcc   = V4L2_PIX_FMT_NV12,
+		.vdownsampling = { 1, 2 },
+		.bit_depth = { 8, 8 },
+		.is_yuv   = true,
+		.planes   = 2,
+		.buffers = 1,
+	},
+	{
+		.name     = "YVU 4:2:0 biplanar",
+		.fourcc   = V4L2_PIX_FMT_NV21,
+		.vdownsampling = { 1, 2 },
+		.bit_depth = { 8, 8 },
+		.is_yuv   = true,
+		.planes   = 2,
+		.buffers = 1,
+	},
+	{
+		.name     = "YUV 4:2:2 biplanar",
+		.fourcc   = V4L2_PIX_FMT_NV16,
+		.vdownsampling = { 1, 1 },
+		.bit_depth = { 8, 8 },
+		.is_yuv   = true,
+		.planes   = 2,
+		.buffers = 1,
+	},
+	{
+		.name     = "YVU 4:2:2 biplanar",
+		.fourcc   = V4L2_PIX_FMT_NV61,
+		.vdownsampling = { 1, 1 },
+		.bit_depth = { 8, 8 },
+		.is_yuv   = true,
+		.planes   = 2,
+		.buffers = 1,
+	},
+	{
+		.name     = "Monochrome",
+		.fourcc   = V4L2_PIX_FMT_GREY,
+		.vdownsampling = { 1 },
+		.bit_depth = { 8 },
+		.is_yuv   = true,
+		.planes   = 1,
+		.buffers = 1,
+	},
+	{
 		.name     = "RGB565 (LE)",
 		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
 		.vdownsampling = { 1 },
@@ -221,10 +293,46 @@ struct vivid_fmt vivid_formats[] = {
 		.buffers = 2,
 		.data_offset = { 0, PLANE0_DATA_OFFSET },
 	},
+	{
+		.name     = "4:2:0, triplanar, YUV",
+		.fourcc   = V4L2_PIX_FMT_YUV420M,
+		.vdownsampling = { 1, 2, 2 },
+		.bit_depth = { 8, 4, 4 },
+		.is_yuv   = true,
+		.planes   = 3,
+		.buffers = 3,
+	},
+	{
+		.name     = "4:2:0, triplanar, YVU",
+		.fourcc   = V4L2_PIX_FMT_YVU420M,
+		.vdownsampling = { 1, 2, 2 },
+		.bit_depth = { 8, 4, 4 },
+		.is_yuv   = true,
+		.planes   = 3,
+		.buffers = 3,
+	},
+	{
+		.name     = "4:2:0, biplanar, YUV",
+		.fourcc   = V4L2_PIX_FMT_NV12M,
+		.vdownsampling = { 1, 2 },
+		.bit_depth = { 8, 8 },
+		.is_yuv   = true,
+		.planes   = 2,
+		.buffers = 2,
+	},
+	{
+		.name     = "4:2:0, biplanar, YVU",
+		.fourcc   = V4L2_PIX_FMT_NV21M,
+		.vdownsampling = { 1, 2 },
+		.bit_depth = { 8, 8 },
+		.is_yuv   = true,
+		.planes   = 2,
+		.buffers = 2,
+	},
 };
 
-/* There are 2 multiplanar formats in the list */
-#define VIVID_MPLANAR_FORMATS 2
+/* There are 6 multiplanar formats in the list */
+#define VIVID_MPLANAR_FORMATS 6
 
 const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
 {
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/29] vivid: add support for 4:2:0 formats
  2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
                   ` (28 preceding siblings ...)
  2015-03-09 15:44 ` [PATCH 29/29] vivid: add the new planar and monochrome formats Hans Verkuil
@ 2015-03-09 16:07 ` Hans Verkuil
  29 siblings, 0 replies; 31+ messages in thread
From: Hans Verkuil @ 2015-03-09 16:07 UTC (permalink / raw)
  To: linux-media

On 03/09/2015 04:44 PM, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> This patch series adds support for most of the 4:2:0 formats that V4L2 has.
> In addition, it fixes various bugs, adds some new features and refactors
> the test pattern generation code.
> 
> The first 8 patches fix bugs and add support for new red/blue checkerboard
> patterns.
> 
> Patches 9-19 add 4:2:0 support to the test pattern generator code.
> 
> Patches 20-25 refactors the test pattern generation function which become
> much, much too large.
> 
> Patches 26-28 add vivid driver support for the 4:2:0 formats and the last
> patch finally enables support for the new formats.
> 
> Besides the new 4:2:0 formats support was also added for PIX_FMT_GREY and
> some missing 4:2:2 formats.

Before I forget: an updated v4l-utils with qv4l2 support for all the new
formats is here:

http://git.linuxtv.org/cgit.cgi/hverkuil/v4l-utils.git/log/?h=yuv420

Regards,

	Hans

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2015-03-09 16:07 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-09 15:44 [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil
2015-03-09 15:44 ` [PATCH 01/29] vivid: the overlay API wasn't disabled completely for multiplanar Hans Verkuil
2015-03-09 15:44 ` [PATCH 02/29] vivid: fix typo in plane size checks Hans Verkuil
2015-03-09 15:44 ` [PATCH 03/29] vivid: wrong top/bottom order for FIELD_ALTERNATE Hans Verkuil
2015-03-09 15:44 ` [PATCH 04/29] vivid: use TPG_MAX_PLANES instead of hardcoding plane-arrays Hans Verkuil
2015-03-09 15:44 ` [PATCH 05/29] vivid: fix test pattern movement for V4L2_FIELD_ALTERNATE Hans Verkuil
2015-03-09 15:44 ` [PATCH 06/29] vivid: add new checkboard patterns Hans Verkuil
2015-03-09 15:44 ` [PATCH 07/29] vivid-tpg: don't add offset when switching to monochrome Hans Verkuil
2015-03-09 15:44 ` [PATCH 08/29] vivid: do not allow video loopback for SEQ_TB/BT Hans Verkuil
2015-03-09 15:44 ` [PATCH 09/29] vivid-tpg: separate planes and buffers Hans Verkuil
2015-03-09 15:44 ` [PATCH 10/29] vivid-tpg: add helper functions for single buffer planar formats Hans Verkuil
2015-03-09 15:44 ` [PATCH 11/29] vivid-tpg: add hor/vert downsampling fields Hans Verkuil
2015-03-09 15:44 ` [PATCH 12/29] vivid-tpg: precalculate downsampled lines Hans Verkuil
2015-03-09 15:44 ` [PATCH 13/29] vivid-tpg: correctly average the two pixels in gen_twopix() Hans Verkuil
2015-03-09 15:44 ` [PATCH 14/29] vivid-tpg: add hor/vert downsampling support to tpg_gen_text Hans Verkuil
2015-03-09 15:44 ` [PATCH 15/29] vivid-tpg: finish hor/vert downsampling support Hans Verkuil
2015-03-09 15:44 ` [PATCH 16/29] vivid-tpg: add support for more planar formats Hans Verkuil
2015-03-09 15:44 ` [PATCH 17/29] vivid-tpg: add support for V4L2_PIX_FMT_GREY Hans Verkuil
2015-03-09 15:44 ` [PATCH 18/29] vivid-tpg: add helper functions to simplify common calculations Hans Verkuil
2015-03-09 15:44 ` [PATCH 19/29] vivid-tpg: add const where appropriate Hans Verkuil
2015-03-09 15:44 ` [PATCH 20/29] vivid-tpg: add a new tpg_draw_params structure Hans Verkuil
2015-03-09 15:44 ` [PATCH 21/29] vivid-tpg: move common parameters to tpg_draw_params Hans Verkuil
2015-03-09 15:44 ` [PATCH 22/29] vivid-tpg: move pattern-related fields to struct tpg_draw_params Hans Verkuil
2015-03-09 15:44 ` [PATCH 23/29] vivid-tpg: move 'extras' parameters to tpg_draw_params Hans Verkuil
2015-03-09 15:44 ` [PATCH 24/29] vivid-tpg: move the 'extras' drawing to a separate function Hans Verkuil
2015-03-09 15:44 ` [PATCH 25/29] vivid-tpg: split off the pattern drawing code Hans Verkuil
2015-03-09 15:44 ` [PATCH 26/29] vivid: add new format fields Hans Verkuil
2015-03-09 15:44 ` [PATCH 27/29] vivid: add support for single buffer planar formats Hans Verkuil
2015-03-09 15:44 ` [PATCH 28/29] vivid: add downsampling support Hans Verkuil
2015-03-09 15:44 ` [PATCH 29/29] vivid: add the new planar and monochrome formats Hans Verkuil
2015-03-09 16:07 ` [PATCH 00/29] vivid: add support for 4:2:0 formats Hans Verkuil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.