V4L/DVB (10211): vivi: Implements 4 inputs on vivi
authorMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 11 Jan 2009 13:29:43 +0000 (10:29 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:42:20 +0000 (12:42 -0300)
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>
drivers/media/video/vivi.c

index 81d5aa5cf3317c336ecbaf7c666e75d793514dab..13e7bd06a80cbce606adc901524d32a3ff39dd0b 100644 (file)
@@ -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);
 }