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