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

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
......@@ -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 */
......@@ -275,9 +333,10 @@ static u8 bars[8][3] = {
#define TO_U(r, g, b) \
(((-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_MIN_Y 24
#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->input = dev->input;
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 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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment