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: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
@@ -223,6 +223,9 @@ struct vivi_dev {
|
|||||||
char timestr[13];
|
char timestr[13];
|
||||||
|
|
||||||
int mv_count; /* Controls bars movement */
|
int mv_count; /* Controls bars movement */
|
||||||
|
|
||||||
|
/* Input Number */
|
||||||
|
int input;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vivi_fh {
|
struct vivi_fh {
|
||||||
@@ -235,6 +238,7 @@ struct vivi_fh {
|
|||||||
|
|
||||||
enum v4l2_buf_type type;
|
enum v4l2_buf_type type;
|
||||||
unsigned char bars[8][3];
|
unsigned char bars[8][3];
|
||||||
|
int input; /* Input Number on bars */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------
|
/* ------------------------------------------------------------------
|
||||||
@@ -254,18 +258,72 @@ enum colors {
|
|||||||
BLACK,
|
BLACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u8 bars[8][3] = {
|
|
||||||
/* R G B */
|
/* R G B */
|
||||||
{204, 204, 204}, /* white */
|
#define COLOR_WHITE {204, 204, 204}
|
||||||
{208, 208, 0}, /* ambar */
|
#define COLOR_AMBAR {208, 208, 0}
|
||||||
{ 0, 206, 206}, /* cyan */
|
#define COLOR_CIAN { 0, 206, 206}
|
||||||
{ 0, 239, 0}, /* green */
|
#define COLOR_GREEN { 0, 239, 0}
|
||||||
{239, 0, 239}, /* magenta */
|
#define COLOR_MAGENTA {239, 0, 239}
|
||||||
{205, 0, 0}, /* red */
|
#define COLOR_RED {205, 0, 0}
|
||||||
{ 0, 0, 255}, /* blue */
|
#define COLOR_BLUE { 0, 0, 255}
|
||||||
{ 0, 0, 0}, /* black */
|
#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) \
|
#define TO_Y(r, g, b) \
|
||||||
(((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
|
(((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
|
||||||
/* RGB to V(Cr) Color transform */
|
/* RGB to V(Cr) Color transform */
|
||||||
@@ -275,9 +333,10 @@ static u8 bars[8][3] = {
|
|||||||
#define TO_U(r, g, b) \
|
#define TO_U(r, g, b) \
|
||||||
(((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
|
(((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
|
||||||
|
|
||||||
#define TSTAMP_MIN_Y 24
|
#define TSTAMP_MIN_Y 24
|
||||||
#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
|
#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
|
||||||
#define TSTAMP_MIN_X 64
|
#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)
|
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 */
|
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)
|
if (TSTAMP_MAX_Y >= hmax)
|
||||||
goto end;
|
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)
|
if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
@@ -807,38 +886,19 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*FIXME: This seems to be generic enough to be at videodev2 */
|
/* precalculate color bar values to speed up rendering */
|
||||||
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
|
static void precalculate_bars(struct vivi_fh *fh)
|
||||||
struct v4l2_format *f)
|
|
||||||
{
|
{
|
||||||
struct vivi_fh *fh = priv;
|
struct vivi_dev *dev = fh->dev;
|
||||||
struct videobuf_queue *q = &fh->vb_vidq;
|
|
||||||
unsigned char r, g, b;
|
unsigned char r, g, b;
|
||||||
int k, is_yuv;
|
int k, is_yuv;
|
||||||
|
|
||||||
int ret = vidioc_try_fmt_vid_cap(file, fh, f);
|
fh->input = dev->input;
|
||||||
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 color bar values to speed up rendering */
|
|
||||||
for (k = 0; k < 8; k++) {
|
for (k = 0; k < 8; k++) {
|
||||||
r = bars[k][0];
|
r = bars[fh->input].bar[k][0];
|
||||||
g = bars[k][1];
|
g = bars[fh->input].bar[k][1];
|
||||||
b = bars[k][2];
|
b = bars[fh->input].bar[k][2];
|
||||||
is_yuv = 0;
|
is_yuv = 0;
|
||||||
|
|
||||||
switch (fh->fmt->fourcc) {
|
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;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&q->vb_lock);
|
mutex_unlock(&q->vb_lock);
|
||||||
|
|
||||||
return (ret);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_reqbufs(struct file *file, void *priv,
|
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,
|
static int vidioc_enum_input(struct file *file, void *priv,
|
||||||
struct v4l2_input *inp)
|
struct v4l2_input *inp)
|
||||||
{
|
{
|
||||||
if (inp->index != 0)
|
if (inp->index >= NUM_INPUTS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
inp->type = V4L2_INPUT_TYPE_CAMERA;
|
inp->type = V4L2_INPUT_TYPE_CAMERA;
|
||||||
inp->std = V4L2_STD_525_60;
|
inp->std = V4L2_STD_525_60;
|
||||||
strcpy(inp->name, "Camera");
|
sprintf(inp->name, "Camera %u", inp->index);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
|
dev->input = i;
|
||||||
|
precalculate_bars(fh);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user