Commit e164b58a authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

V4L/DVB (10211): vivi: Implements 4 inputs on vivi



This patch adds the capability of selecting between 4 different inputs
on vivi driver. Input 0 is the normal color bar, while inputs 1-3 are
modified color bars.

This allows testing input selection on userspace applications and
serves as an implementation model for other drivers.

The current approach allows a maximum of 10 different inputs, since the
input name generator assumes that we need just one digit to present the
input. It shouldn't be hard to modify it to present a bigger name of
inputs, but, in fact, it doesn't make much sense of doing it for this
test driver.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0d34fb8e
Loading
Loading
Loading
Loading
+142 −44
Original line number Diff line number Diff line
@@ -223,6 +223,9 @@ struct vivi_dev {
	char                       timestr[13];

	int			   mv_count;	/* Controls bars movement */

	/* Input Number */
	int			   input;
};

struct vivi_fh {
@@ -235,6 +238,7 @@ struct vivi_fh {

	enum v4l2_buf_type         type;
	unsigned char              bars[8][3];
	int			   input; 	/* Input Number on bars */
};

/* ------------------------------------------------------------------
@@ -254,18 +258,72 @@ enum colors {
	BLACK,
};

static u8 bars[8][3] = {
	/* R   G   B */
	{204, 204, 204},  /* white */
	{208, 208,   0},  /* ambar */
	{  0, 206, 206},  /* cyan */
	{  0, 239,   0},  /* green */
	{239,   0, 239},  /* magenta */
	{205,   0,   0},  /* red */
	{  0,   0, 255},  /* blue */
	{  0,   0,   0},  /* black */
#define COLOR_WHITE	{204, 204, 204}
#define COLOR_AMBAR	{208, 208,   0}
#define COLOR_CIAN	{  0, 206, 206}
#define	COLOR_GREEN	{  0, 239,   0}
#define COLOR_MAGENTA	{239,   0, 239}
#define COLOR_RED	{205,   0,   0}
#define COLOR_BLUE	{  0,   0, 255}
#define COLOR_BLACK	{  0,   0,   0}

struct bar_std {
	u8 bar[8][3];
};

/* Maximum number of bars are 10 - otherwise, the input print code
   should be modified */
static struct bar_std bars[] = {
	{	/* Standard ITU-R color bar sequence */
		{
			COLOR_WHITE,
			COLOR_AMBAR,
			COLOR_CIAN,
			COLOR_GREEN,
			COLOR_MAGENTA,
			COLOR_RED,
			COLOR_BLUE,
			COLOR_BLACK,
		}
	}, {
		{
			COLOR_WHITE,
			COLOR_AMBAR,
			COLOR_BLACK,
			COLOR_WHITE,
			COLOR_AMBAR,
			COLOR_BLACK,
			COLOR_WHITE,
			COLOR_AMBAR,
		}
	}, {
		{
			COLOR_WHITE,
			COLOR_CIAN,
			COLOR_BLACK,
			COLOR_WHITE,
			COLOR_CIAN,
			COLOR_BLACK,
			COLOR_WHITE,
			COLOR_CIAN,
		}
	}, {
		{
			COLOR_WHITE,
			COLOR_GREEN,
			COLOR_BLACK,
			COLOR_WHITE,
			COLOR_GREEN,
			COLOR_BLACK,
			COLOR_WHITE,
			COLOR_GREEN,
		}
	},
};

#define NUM_INPUTS ARRAY_SIZE(bars)

#define TO_Y(r, g, b) \
	(((16829 * r + 33039 * g + 6416 * b  + 32768) >> 16) + 16)
/* RGB to  V(Cr) Color transform */
@@ -276,8 +334,9 @@ static u8 bars[8][3] = {
	(((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)

#define TSTAMP_MIN_Y	24
#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
#define TSTAMP_MIN_X 64
#define TSTAMP_MAX_Y	(TSTAMP_MIN_Y + 15)
#define TSTAMP_INPUT_X	10
#define TSTAMP_MIN_X	(54 + TSTAMP_INPUT_X)

static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
{
@@ -392,9 +451,29 @@ static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
		pos += 4; /* only 16 bpp supported for now */
	}

	/* Checks if it is possible to show timestamp */
	/* Prints input entry number */

	/* Checks if it is possible to input number */
	if (TSTAMP_MAX_Y >= hmax)
		goto end;

	if (TSTAMP_INPUT_X + strlen(timestr) >= wmax)
		goto end;

	if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
		chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y];
		pos = TSTAMP_INPUT_X;
		for (i = 0; i < 7; i++) {
			/* Draw white font on black background */
			if (chr & 1 << (7 - i))
				gen_twopix(fh, basep + pos, WHITE);
			else
				gen_twopix(fh, basep + pos, BLACK);
			pos += 2;
		}
	}

	/* Checks if it is possible to show timestamp */
	if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
		goto end;

@@ -807,38 +886,19 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
	return 0;
}

/*FIXME: This seems to be generic enough to be at videodev2 */
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
					struct v4l2_format *f)
/* precalculate color bar values to speed up rendering */
static void precalculate_bars(struct vivi_fh *fh)
{
	struct vivi_fh  *fh = priv;
	struct videobuf_queue *q = &fh->vb_vidq;
	struct vivi_dev *dev = fh->dev;
	unsigned char r, g, b;
	int k, is_yuv;

	int ret = vidioc_try_fmt_vid_cap(file, fh, f);
	if (ret < 0)
		return (ret);

	mutex_lock(&q->vb_lock);

	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
		dprintk(fh->dev, 1, "%s queue busy\n", __func__);
		ret = -EBUSY;
		goto out;
	}

	fh->fmt           = get_format(f);
	fh->width         = f->fmt.pix.width;
	fh->height        = f->fmt.pix.height;
	fh->vb_vidq.field = f->fmt.pix.field;
	fh->type          = f->type;
	fh->input = dev->input;

	/* precalculate color bar values to speed up rendering */
	for (k = 0; k < 8; k++) {
		r = bars[k][0];
		g = bars[k][1];
		b = bars[k][2];
		r = bars[fh->input].bar[k][0];
		g = bars[fh->input].bar[k][1];
		b = bars[fh->input].bar[k][2];
		is_yuv = 0;

		switch (fh->fmt->fourcc) {
@@ -871,11 +931,40 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
		}
	}

}

/*FIXME: This seems to be generic enough to be at videodev2 */
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
					struct v4l2_format *f)
{
	struct vivi_fh *fh = priv;
	struct videobuf_queue *q = &fh->vb_vidq;

	int ret = vidioc_try_fmt_vid_cap(file, fh, f);
	if (ret < 0)
		return ret;

	mutex_lock(&q->vb_lock);

	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
		dprintk(fh->dev, 1, "%s queue busy\n", __func__);
		ret = -EBUSY;
		goto out;
	}

	fh->fmt           = get_format(f);
	fh->width         = f->fmt.pix.width;
	fh->height        = f->fmt.pix.height;
	fh->vb_vidq.field = f->fmt.pix.field;
	fh->type          = f->type;

	precalculate_bars(fh);

	ret = 0;
out:
	mutex_unlock(&q->vb_lock);

	return (ret);
	return ret;
}

static int vidioc_reqbufs(struct file *file, void *priv,
@@ -950,27 +1039,36 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
static int vidioc_enum_input(struct file *file, void *priv,
				struct v4l2_input *inp)
{
	if (inp->index != 0)
	if (inp->index >= NUM_INPUTS)
		return -EINVAL;

	inp->type = V4L2_INPUT_TYPE_CAMERA;
	inp->std = V4L2_STD_525_60;
	strcpy(inp->name, "Camera");
	sprintf(inp->name, "Camera %u", inp->index);

	return (0);
}

static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
	*i = 0;
	struct vivi_fh *fh = priv;
	struct vivi_dev *dev = fh->dev;

	*i = dev->input;

	return (0);
}
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
	if (i > 0)
	struct vivi_fh *fh = priv;
	struct vivi_dev *dev = fh->dev;

	if (i >= NUM_INPUTS)
		return -EINVAL;

	dev->input = i;
	precalculate_bars(fh);

	return (0);
}