V4L/DVB (9236): Teach vivi about multiple pixel formats

This patch contains the ground work to add support for multiple
pixel formats to vivi.c

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Magnus Damm 2008-10-14 12:47:09 -03:00 committed by Mauro Carvalho Chehab
parent 74d7c5af78
commit d891f47581
1 changed files with 67 additions and 30 deletions

View File

@ -128,12 +128,31 @@ struct vivi_fmt {
int depth;
};
static struct vivi_fmt format = {
.name = "4:2:2, packed, YUYV",
.fourcc = V4L2_PIX_FMT_YUYV,
.depth = 16,
static struct vivi_fmt formats[] = {
{
.name = "4:2:2, packed, YUYV",
.fourcc = V4L2_PIX_FMT_YUYV,
.depth = 16,
},
};
static struct vivi_fmt *get_format(struct v4l2_format *f)
{
struct vivi_fmt *fmt;
unsigned int k;
for (k = 0; k < ARRAY_SIZE(formats); k++) {
fmt = &formats[k];
if (fmt->fourcc == f->fmt.pix.pixelformat)
break;
}
if (k == ARRAY_SIZE(formats))
return NULL;
return &formats[k];
}
struct sg_to_addr {
int pos;
struct scatterlist *sg;
@ -248,16 +267,20 @@ static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
for (color = 0; color < 4; color++) {
p = buf + color;
switch (color) {
case 0:
case 2:
*p = r_y;
break;
case 1:
*p = g_u;
break;
case 3:
*p = b_v;
switch (fh->fmt->fourcc) {
case V4L2_PIX_FMT_YUYV:
switch (color) {
case 0:
case 2:
*p = r_y;
break;
case 1:
*p = g_u;
break;
case 3:
*p = b_v;
break;
}
break;
}
}
@ -622,11 +645,15 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index > 0)
struct vivi_fmt *fmt;
if (f->index >= ARRAY_SIZE(formats))
return -EINVAL;
strlcpy(f->description, format.name, sizeof(f->description));
f->pixelformat = format.fourcc;
fmt = &formats[f->index];
strlcpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
}
@ -656,13 +683,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
enum v4l2_field field;
unsigned int maxw, maxh;
if (format.fourcc != f->fmt.pix.pixelformat) {
dprintk(dev, 1, "Fourcc format (0x%08x) invalid. "
"Driver accepts only 0x%08x\n",
f->fmt.pix.pixelformat, format.fourcc);
fmt = get_format(f);
if (!fmt) {
dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
f->fmt.pix.pixelformat);
return -EINVAL;
}
fmt = &format;
field = f->fmt.pix.field;
@ -701,7 +727,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct vivi_fh *fh = priv;
struct videobuf_queue *q = &fh->vb_vidq;
unsigned char r, g, b;
int k;
int k, is_yuv;
int ret = vidioc_try_fmt_vid_cap(file, fh, f);
if (ret < 0)
@ -715,7 +741,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
goto out;
}
fh->fmt = &format;
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;
@ -726,10 +752,23 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
r = bars[k][0];
g = bars[k][1];
b = bars[k][2];
is_yuv = 0;
fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
fh->bars[k][1] = TO_U(r, g, b); /* Cb */
fh->bars[k][2] = TO_V(r, g, b); /* Cr */
switch (fh->fmt->fourcc) {
case V4L2_PIX_FMT_YUYV:
is_yuv = 1;
break;
}
if (is_yuv) {
fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
fh->bars[k][1] = TO_U(r, g, b); /* Cb */
fh->bars[k][2] = TO_V(r, g, b); /* Cr */
} else {
fh->bars[k][0] = r;
fh->bars[k][1] = g;
fh->bars[k][2] = b;
}
}
ret = 0;
@ -885,8 +924,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
File operations for the device
------------------------------------------------------------------*/
#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8)
static int vivi_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
@ -935,7 +972,7 @@ unlock:
fh->dev = dev;
fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fh->fmt = &format;
fh->fmt = &formats[0];
fh->width = 640;
fh->height = 480;