mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-21 17:00:01 +00:00
[media] bw-qcam: driver and pixfmt documentation fixes
Fix the documentation of the Y4 and Y6 formats. Fix a poll() issue, add support for enum_frmsizes, set the proper parent device and fix a few compliance issues. Tested with an actual Connectix B&W parallel port webcam, both on a little-endian and a big-endian platform. This driver has never been so good, doing 320x240 at 1 frame per second :-) I know, nobody cares, but still it is cool that linux can still support this old webcam. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
6ba4c432dc
commit
de87897af0
@ -986,13 +986,13 @@ http://www.thedirks.org/winnov/</ulink></para></entry>
|
|||||||
<row id="V4L2-PIX-FMT-Y4">
|
<row id="V4L2-PIX-FMT-Y4">
|
||||||
<entry><constant>V4L2_PIX_FMT_Y4</constant></entry>
|
<entry><constant>V4L2_PIX_FMT_Y4</constant></entry>
|
||||||
<entry>'Y04 '</entry>
|
<entry>'Y04 '</entry>
|
||||||
<entry>Old 4-bit greyscale format. Only the least significant 4 bits of each byte are used,
|
<entry>Old 4-bit greyscale format. Only the most significant 4 bits of each byte are used,
|
||||||
the other bits are set to 0.</entry>
|
the other bits are set to 0.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row id="V4L2-PIX-FMT-Y6">
|
<row id="V4L2-PIX-FMT-Y6">
|
||||||
<entry><constant>V4L2_PIX_FMT_Y6</constant></entry>
|
<entry><constant>V4L2_PIX_FMT_Y6</constant></entry>
|
||||||
<entry>'Y06 '</entry>
|
<entry>'Y06 '</entry>
|
||||||
<entry>Old 6-bit greyscale format. Only the least significant 6 bits of each byte are used,
|
<entry>Old 6-bit greyscale format. Only the most significant 6 bits of each byte are used,
|
||||||
the other bits are set to 0.</entry>
|
the other bits are set to 0.</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -607,8 +607,9 @@ static long qc_capture(struct qcam *q, char __user *buf, unsigned long len)
|
|||||||
}
|
}
|
||||||
o = i * pixels_per_line + pixels_read + k;
|
o = i * pixels_per_line + pixels_read + k;
|
||||||
if (o < len) {
|
if (o < len) {
|
||||||
|
u8 ch = invert - buffer[k];
|
||||||
got++;
|
got++;
|
||||||
put_user((invert - buffer[k]) << shift, buf + o);
|
put_user(ch << shift, buf + o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pixels_read += bytes;
|
pixels_read += bytes;
|
||||||
@ -648,8 +649,8 @@ static int qcam_querycap(struct file *file, void *priv,
|
|||||||
struct qcam *qcam = video_drvdata(file);
|
struct qcam *qcam = video_drvdata(file);
|
||||||
|
|
||||||
strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
|
strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
|
||||||
strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card));
|
strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card));
|
||||||
strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
|
strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info));
|
||||||
vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
|
vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
|
||||||
vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
|
vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
|
||||||
return 0;
|
return 0;
|
||||||
@ -688,8 +689,8 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
|
|||||||
pix->height = qcam->height / qcam->transfer_scale;
|
pix->height = qcam->height / qcam->transfer_scale;
|
||||||
pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
|
pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
|
||||||
pix->field = V4L2_FIELD_NONE;
|
pix->field = V4L2_FIELD_NONE;
|
||||||
pix->bytesperline = qcam->width;
|
pix->bytesperline = pix->width;
|
||||||
pix->sizeimage = qcam->width * qcam->height;
|
pix->sizeimage = pix->width * pix->height;
|
||||||
/* Just a guess */
|
/* Just a guess */
|
||||||
pix->colorspace = V4L2_COLORSPACE_SRGB;
|
pix->colorspace = V4L2_COLORSPACE_SRGB;
|
||||||
return 0;
|
return 0;
|
||||||
@ -757,7 +758,7 @@ static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdes
|
|||||||
"4-Bit Monochrome", V4L2_PIX_FMT_Y4,
|
"4-Bit Monochrome", V4L2_PIX_FMT_Y4,
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
},
|
},
|
||||||
{ 0, 0, 0,
|
{ 1, 0, 0,
|
||||||
"6-Bit Monochrome", V4L2_PIX_FMT_Y6,
|
"6-Bit Monochrome", V4L2_PIX_FMT_Y6,
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
},
|
},
|
||||||
@ -772,6 +773,25 @@ static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdes
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qcam_enum_framesizes(struct file *file, void *fh,
|
||||||
|
struct v4l2_frmsizeenum *fsize)
|
||||||
|
{
|
||||||
|
static const struct v4l2_frmsize_discrete sizes[] = {
|
||||||
|
{ 80, 60 },
|
||||||
|
{ 160, 120 },
|
||||||
|
{ 320, 240 },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fsize->index > 2)
|
||||||
|
return -EINVAL;
|
||||||
|
if (fsize->pixel_format != V4L2_PIX_FMT_Y4 &&
|
||||||
|
fsize->pixel_format != V4L2_PIX_FMT_Y6)
|
||||||
|
return -EINVAL;
|
||||||
|
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||||
|
fsize->discrete = sizes[fsize->index];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t qcam_read(struct file *file, char __user *buf,
|
static ssize_t qcam_read(struct file *file, char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
@ -795,6 +815,11 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int qcam_poll(struct file *filp, poll_table *wait)
|
||||||
|
{
|
||||||
|
return v4l2_ctrl_poll(filp, wait) | POLLIN | POLLRDNORM;
|
||||||
|
}
|
||||||
|
|
||||||
static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
|
static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
struct qcam *qcam =
|
struct qcam *qcam =
|
||||||
@ -828,7 +853,7 @@ static const struct v4l2_file_operations qcam_fops = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = v4l2_fh_open,
|
.open = v4l2_fh_open,
|
||||||
.release = v4l2_fh_release,
|
.release = v4l2_fh_release,
|
||||||
.poll = v4l2_ctrl_poll,
|
.poll = qcam_poll,
|
||||||
.unlocked_ioctl = video_ioctl2,
|
.unlocked_ioctl = video_ioctl2,
|
||||||
.read = qcam_read,
|
.read = qcam_read,
|
||||||
};
|
};
|
||||||
@ -839,6 +864,7 @@ static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
|
|||||||
.vidioc_s_input = qcam_s_input,
|
.vidioc_s_input = qcam_s_input,
|
||||||
.vidioc_enum_input = qcam_enum_input,
|
.vidioc_enum_input = qcam_enum_input,
|
||||||
.vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
|
.vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
|
||||||
|
.vidioc_enum_framesizes = qcam_enum_framesizes,
|
||||||
.vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
|
.vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
|
||||||
.vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
|
.vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
|
||||||
.vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
|
.vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
|
||||||
@ -864,9 +890,9 @@ static struct qcam *qcam_init(struct parport *port)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
v4l2_dev = &qcam->v4l2_dev;
|
v4l2_dev = &qcam->v4l2_dev;
|
||||||
strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name));
|
snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%d", num_cams);
|
||||||
|
|
||||||
if (v4l2_device_register(NULL, v4l2_dev) < 0) {
|
if (v4l2_device_register(port->dev, v4l2_dev) < 0) {
|
||||||
v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
|
v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
|
||||||
kfree(qcam);
|
kfree(qcam);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -886,7 +912,7 @@ static struct qcam *qcam_init(struct parport *port)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
qcam->pport = port;
|
qcam->pport = port;
|
||||||
qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
|
qcam->pdev = parport_register_device(port, v4l2_dev->name, NULL, NULL,
|
||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
if (qcam->pdev == NULL) {
|
if (qcam->pdev == NULL) {
|
||||||
v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
|
v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
|
||||||
@ -975,6 +1001,7 @@ static int init_bwqcam(struct parport *port)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
qc_calibrate(qcam);
|
qc_calibrate(qcam);
|
||||||
|
v4l2_ctrl_handler_setup(&qcam->hdl);
|
||||||
|
|
||||||
parport_release(qcam->pdev);
|
parport_release(qcam->pdev);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user