mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
[media] pwc: Remove software emulation of arbritary resolutions
The pwc driver claims to support any resolution between 160x120 and 640x480, but emulates this by simply drawing a black border around the image. Userspace can draw its own black border if it really wants one. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
a08d2c7271
commit
795e6eb326
8 changed files with 93 additions and 223 deletions
|
@ -460,16 +460,6 @@ Who: Jean Delvare <khali@linux-fr.org>
|
|||
|
||||
----------------------------
|
||||
|
||||
What: Software emulation of arbritary resolutions in the pwc driver
|
||||
When: 3.3
|
||||
Why: The pwc driver claims to support any resolution between 160x120
|
||||
and 640x480, but emulates this by simply drawing a black border
|
||||
around the image. Userspace can draw its own black border if it
|
||||
really wants one.
|
||||
Who: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: For VIDIOC_S_FREQUENCY the type field must match the device node's type.
|
||||
If not, return -EINVAL.
|
||||
When: 3.2
|
||||
|
|
|
@ -102,8 +102,6 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
|
|||
#include "pwc-nala.h"
|
||||
};
|
||||
|
||||
static void pwc_set_image_buffer_size(struct pwc_device *pdev);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int _send_control_msg(struct pwc_device *pdev,
|
||||
|
@ -221,8 +219,9 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
|
|||
/* Set various parameters */
|
||||
pdev->vframes = frames;
|
||||
pdev->valternate = pEntry->alternate;
|
||||
pdev->image = pwc_image_sizes[size];
|
||||
pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
|
||||
pdev->width = pwc_image_sizes[size][0];
|
||||
pdev->height = pwc_image_sizes[size][1];
|
||||
pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
|
||||
if (pEntry->compressed) {
|
||||
if (pdev->release < 5) { /* 4 fold compression */
|
||||
pdev->vbandlength = 528;
|
||||
|
@ -282,12 +281,13 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
|
|||
/* Set various parameters */
|
||||
pdev->vframes = frames;
|
||||
pdev->valternate = pChoose->alternate;
|
||||
pdev->image = pwc_image_sizes[size];
|
||||
pdev->width = pwc_image_sizes[size][0];
|
||||
pdev->height = pwc_image_sizes[size][1];
|
||||
pdev->vbandlength = pChoose->bandlength;
|
||||
if (pChoose->bandlength > 0)
|
||||
pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
|
||||
pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
|
||||
else
|
||||
pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
|
||||
pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -339,37 +339,25 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
|
|||
/* All set and go */
|
||||
pdev->vframes = frames;
|
||||
pdev->valternate = pChoose->alternate;
|
||||
pdev->image = pwc_image_sizes[size];
|
||||
pdev->width = pwc_image_sizes[size][0];
|
||||
pdev->height = pwc_image_sizes[size][1];
|
||||
pdev->vbandlength = pChoose->bandlength;
|
||||
if (pdev->vbandlength > 0)
|
||||
pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
|
||||
pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
|
||||
else
|
||||
pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
|
||||
pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
|
||||
PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
|
||||
pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@pdev: device structure
|
||||
@width: viewport width
|
||||
@height: viewport height
|
||||
@frame: framerate, in fps
|
||||
@compression: preferred compression ratio
|
||||
*/
|
||||
int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
|
||||
int frames, int compression)
|
||||
{
|
||||
int ret, size;
|
||||
|
||||
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
|
||||
size = pwc_decode_size(pdev, width, height);
|
||||
if (size < 0) {
|
||||
PWC_DEBUG_MODULE("Could not find suitable size.\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
size = pwc_get_size(pdev, width, height);
|
||||
PWC_TRACE("decode_size = %d.\n", size);
|
||||
|
||||
if (DEVICE_USE_CODEC1(pdev->type)) {
|
||||
|
@ -385,12 +373,9 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
|
|||
PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
|
||||
return ret;
|
||||
}
|
||||
pdev->view.x = width;
|
||||
pdev->view.y = height;
|
||||
pdev->vcompression = compression;
|
||||
pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
|
||||
pwc_set_image_buffer_size(pdev);
|
||||
PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
|
||||
PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -447,34 +432,6 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void pwc_set_image_buffer_size(struct pwc_device *pdev)
|
||||
{
|
||||
int factor = 0;
|
||||
|
||||
/* for V4L2_PIX_FMT_YUV420 */
|
||||
switch (pdev->pixfmt) {
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
factor = 6;
|
||||
break;
|
||||
case V4L2_PIX_FMT_PWC1:
|
||||
case V4L2_PIX_FMT_PWC2:
|
||||
factor = 6; /* can be uncompressed YUV420P */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set sizes in bytes */
|
||||
pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
|
||||
pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
|
||||
|
||||
/* Align offset, or you'll get some very weird results in
|
||||
YUV420 mode... x must be multiple of 4 (to get the Y's in
|
||||
place), and y even (or you'll mixup U & V). This is less of a
|
||||
problem for YUV420P.
|
||||
*/
|
||||
pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
|
||||
pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
|
||||
}
|
||||
|
||||
int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -656,10 +656,6 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
|
|||
*
|
||||
* Uncompress a pwc23 buffer.
|
||||
*
|
||||
* pwc.view: size of the image wanted
|
||||
* pwc.image: size of the image returned by the camera
|
||||
* pwc.offset: (x,y) to displayer image in the view
|
||||
*
|
||||
* src: raw data
|
||||
* dst: image output
|
||||
*/
|
||||
|
@ -667,7 +663,7 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
|
|||
const void *src,
|
||||
void *dst)
|
||||
{
|
||||
int bandlines_left, stride, bytes_per_block;
|
||||
int bandlines_left, bytes_per_block;
|
||||
struct pwc_dec23_private *pdec = pwc->decompress_data;
|
||||
|
||||
/* YUV420P image format */
|
||||
|
@ -678,28 +674,23 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
|
|||
|
||||
mutex_lock(&pdec->lock);
|
||||
|
||||
bandlines_left = pwc->image.y / 4;
|
||||
bytes_per_block = pwc->view.x * 4;
|
||||
plane_size = pwc->view.x * pwc->view.y;
|
||||
bandlines_left = pwc->height / 4;
|
||||
bytes_per_block = pwc->width * 4;
|
||||
plane_size = pwc->height * pwc->width;
|
||||
|
||||
/* offset in Y plane */
|
||||
stride = pwc->view.x * pwc->offset.y;
|
||||
pout_planar_y = dst + stride + pwc->offset.x;
|
||||
|
||||
/* offsets in U/V planes */
|
||||
stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2;
|
||||
pout_planar_u = dst + plane_size + stride;
|
||||
pout_planar_v = dst + plane_size + plane_size / 4 + stride;
|
||||
pout_planar_y = dst;
|
||||
pout_planar_u = dst + plane_size;
|
||||
pout_planar_v = dst + plane_size + plane_size / 4;
|
||||
|
||||
while (bandlines_left--) {
|
||||
DecompressBand23(pwc->decompress_data,
|
||||
src,
|
||||
pout_planar_y, pout_planar_u, pout_planar_v,
|
||||
pwc->image.x, pwc->view.x);
|
||||
pwc->width, pwc->width);
|
||||
src += pwc->vbandlength;
|
||||
pout_planar_y += bytes_per_block;
|
||||
pout_planar_u += pwc->view.x;
|
||||
pout_planar_v += pwc->view.x;
|
||||
pout_planar_u += pwc->width;
|
||||
pout_planar_v += pwc->width;
|
||||
}
|
||||
mutex_unlock(&pdec->lock);
|
||||
}
|
||||
|
|
|
@ -656,6 +656,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
|
|||
unsigned int sizes[], void *alloc_ctxs[])
|
||||
{
|
||||
struct pwc_device *pdev = vb2_get_drv_priv(vq);
|
||||
int size;
|
||||
|
||||
if (*nbuffers < MIN_FRAMES)
|
||||
*nbuffers = MIN_FRAMES;
|
||||
|
@ -664,7 +665,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
|
|||
|
||||
*nplanes = 1;
|
||||
|
||||
sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
|
||||
size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
|
||||
sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
|
||||
pwc_image_sizes[size][1] * 3 / 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -742,7 +745,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
|
|||
pwc_camera_power(pdev, 1);
|
||||
if (pdev->power_save) {
|
||||
/* Restore video mode */
|
||||
pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
|
||||
pwc_set_video_mode(pdev, pdev->width, pdev->height,
|
||||
pdev->vframes, pdev->vcompression);
|
||||
}
|
||||
pwc_set_leds(pdev, led_on, led_off);
|
||||
|
@ -1056,7 +1059,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
}
|
||||
pdev->type = type_id;
|
||||
pdev->vframes = default_fps;
|
||||
strcpy(pdev->serial, serial_number);
|
||||
pdev->features = features;
|
||||
pwc_construct(pdev); /* set min/max sizes correct */
|
||||
|
||||
|
@ -1119,7 +1121,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
pwc_set_leds(pdev, 0, 0);
|
||||
|
||||
/* Setup intial videomode */
|
||||
rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
|
||||
rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
|
||||
pdev->vframes, pdev->vcompression);
|
||||
if (rc)
|
||||
goto err_free_mem;
|
||||
|
|
|
@ -27,67 +27,47 @@
|
|||
|
||||
#include "pwc.h"
|
||||
|
||||
const struct pwc_coord pwc_image_sizes[PSZ_MAX] =
|
||||
const int pwc_image_sizes[PSZ_MAX][2] =
|
||||
{
|
||||
{ 128, 96, 0 }, /* sqcif */
|
||||
{ 160, 120, 0 }, /* qsif */
|
||||
{ 176, 144, 0 }, /* qcif */
|
||||
{ 320, 240, 0 }, /* sif */
|
||||
{ 352, 288, 0 }, /* cif */
|
||||
{ 640, 480, 0 }, /* vga */
|
||||
{ 128, 96 }, /* sqcif */
|
||||
{ 160, 120 }, /* qsif */
|
||||
{ 176, 144 }, /* qcif */
|
||||
{ 320, 240 }, /* sif */
|
||||
{ 352, 288 }, /* cif */
|
||||
{ 640, 480 }, /* vga */
|
||||
};
|
||||
|
||||
/* x,y -> PSZ_ */
|
||||
int pwc_decode_size(struct pwc_device *pdev, int width, int height)
|
||||
int pwc_get_size(struct pwc_device *pdev, int width, int height)
|
||||
{
|
||||
int i, find;
|
||||
|
||||
/* Make sure we don't go beyond our max size.
|
||||
NB: we have different limits for RAW and normal modes. In case
|
||||
you don't have the decompressor loaded or use RAW mode,
|
||||
the maximum viewable size is smaller.
|
||||
*/
|
||||
if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
|
||||
{
|
||||
if (width > pdev->abs_max.x || height > pdev->abs_max.y)
|
||||
{
|
||||
PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (width > pdev->view_max.x || height > pdev->view_max.y)
|
||||
{
|
||||
PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
|
||||
/* Find the largest size supported by the camera that fits into the
|
||||
requested size.
|
||||
*/
|
||||
find = -1;
|
||||
for (i = 0; i < PSZ_MAX; i++) {
|
||||
if (pdev->image_mask & (1 << i)) {
|
||||
if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
|
||||
find = i;
|
||||
}
|
||||
requested size. */
|
||||
for (i = PSZ_MAX - 1; i >= 0; i--) {
|
||||
if (!(pdev->image_mask & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (pwc_image_sizes[i][0] <= width &&
|
||||
pwc_image_sizes[i][1] <= height)
|
||||
return i;
|
||||
}
|
||||
return find;
|
||||
|
||||
/* No mode found, return the smallest mode we have */
|
||||
for (i = 0; i < PSZ_MAX; i++) {
|
||||
if (pdev->image_mask & (1 << i))
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Never reached there always is atleast one supported mode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* initialize variables depending on type and decompressor*/
|
||||
/* initialize variables depending on type and decompressor */
|
||||
void pwc_construct(struct pwc_device *pdev)
|
||||
{
|
||||
if (DEVICE_USE_CODEC1(pdev->type)) {
|
||||
|
||||
pdev->view_min.x = 128;
|
||||
pdev->view_min.y = 96;
|
||||
pdev->view_max.x = 352;
|
||||
pdev->view_max.y = 288;
|
||||
pdev->abs_max.x = 352;
|
||||
pdev->abs_max.y = 288;
|
||||
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
|
||||
pdev->vcinterface = 2;
|
||||
pdev->vendpoint = 4;
|
||||
|
@ -96,13 +76,7 @@ void pwc_construct(struct pwc_device *pdev)
|
|||
|
||||
} else if (DEVICE_USE_CODEC3(pdev->type)) {
|
||||
|
||||
pdev->view_min.x = 160;
|
||||
pdev->view_min.y = 120;
|
||||
pdev->view_max.x = 640;
|
||||
pdev->view_max.y = 480;
|
||||
pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
|
||||
pdev->abs_max.x = 640;
|
||||
pdev->abs_max.y = 480;
|
||||
pdev->vcinterface = 3;
|
||||
pdev->vendpoint = 5;
|
||||
pdev->frame_header_size = TOUCAM_HEADER_SIZE;
|
||||
|
@ -110,20 +84,11 @@ void pwc_construct(struct pwc_device *pdev)
|
|||
|
||||
} else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
|
||||
|
||||
pdev->view_min.x = 128;
|
||||
pdev->view_min.y = 96;
|
||||
/* Anthill bug #38: PWC always reports max size, even without PWCX */
|
||||
pdev->view_max.x = 640;
|
||||
pdev->view_max.y = 480;
|
||||
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
|
||||
pdev->abs_max.x = 640;
|
||||
pdev->abs_max.y = 480;
|
||||
pdev->vcinterface = 3;
|
||||
pdev->vendpoint = 4;
|
||||
pdev->frame_header_size = 0;
|
||||
pdev->frame_trailer_size = 0;
|
||||
}
|
||||
pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
|
||||
pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
|
||||
pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
|
||||
{
|
||||
int n, line, col, stride;
|
||||
int n, line, col;
|
||||
void *yuv, *image;
|
||||
u16 *src;
|
||||
u16 *dsty, *dstu, *dstv;
|
||||
|
@ -60,35 +60,23 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
vb2_set_plane_payload(&fbuf->vb, 0, pdev->view.size);
|
||||
vb2_set_plane_payload(&fbuf->vb, 0,
|
||||
pdev->width * pdev->height * 3 / 2);
|
||||
|
||||
if (pdev->vbandlength == 0) {
|
||||
/* Uncompressed mode.
|
||||
* We copy the data into the output buffer, using the viewport
|
||||
* size (which may be larger than the image size).
|
||||
* Unfortunately we have to do a bit of byte stuffing to get
|
||||
* the desired output format/size.
|
||||
*
|
||||
* We do some byte shuffling here to go from the
|
||||
* native format to YUV420P.
|
||||
*/
|
||||
src = (u16 *)yuv;
|
||||
n = pdev->view.x * pdev->view.y;
|
||||
n = pdev->width * pdev->height;
|
||||
dsty = (u16 *)(image);
|
||||
dstu = (u16 *)(image + n);
|
||||
dstv = (u16 *)(image + n + n / 4);
|
||||
|
||||
/* offset in Y plane */
|
||||
stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
|
||||
dsty = (u16 *)(image + stride);
|
||||
|
||||
/* offsets in U/V planes */
|
||||
stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
|
||||
dstu = (u16 *)(image + n + stride);
|
||||
dstv = (u16 *)(image + n + n / 4 + stride);
|
||||
|
||||
/* increment after each line */
|
||||
stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
|
||||
|
||||
for (line = 0; line < pdev->image.y; line++) {
|
||||
for (col = 0; col < pdev->image.x; col += 4) {
|
||||
for (line = 0; line < pdev->height; line++) {
|
||||
for (col = 0; col < pdev->width; col += 4) {
|
||||
*dsty++ = *src++;
|
||||
*dsty++ = *src++;
|
||||
if (line & 1)
|
||||
|
@ -96,11 +84,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
|
|||
else
|
||||
*dstu++ = *src++;
|
||||
}
|
||||
dsty += stride;
|
||||
if (line & 1)
|
||||
dstv += (stride >> 1);
|
||||
else
|
||||
dstu += (stride >> 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -122,6 +105,3 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
|
||||
|
|
|
@ -398,8 +398,8 @@ int pwc_init_controls(struct pwc_device *pdev)
|
|||
static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
|
||||
{
|
||||
memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
|
||||
f->fmt.pix.width = pdev->view.x;
|
||||
f->fmt.pix.height = pdev->view.y;
|
||||
f->fmt.pix.width = pdev->width;
|
||||
f->fmt.pix.height = pdev->height;
|
||||
f->fmt.pix.field = V4L2_FIELD_NONE;
|
||||
if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
|
||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
|
||||
|
@ -429,6 +429,8 @@ static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_forma
|
|||
/* ioctl(VIDIOC_TRY_FMT) */
|
||||
static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
|
||||
PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
|
||||
return -EINVAL;
|
||||
|
@ -455,15 +457,9 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
|
|||
|
||||
}
|
||||
|
||||
if (f->fmt.pix.width > pdev->view_max.x)
|
||||
f->fmt.pix.width = pdev->view_max.x;
|
||||
else if (f->fmt.pix.width < pdev->view_min.x)
|
||||
f->fmt.pix.width = pdev->view_min.x;
|
||||
|
||||
if (f->fmt.pix.height > pdev->view_max.y)
|
||||
f->fmt.pix.height = pdev->view_max.y;
|
||||
else if (f->fmt.pix.height < pdev->view_min.y)
|
||||
f->fmt.pix.height = pdev->view_min.y;
|
||||
size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
|
||||
f->fmt.pix.width = pwc_image_sizes[size][0];
|
||||
f->fmt.pix.height = pwc_image_sizes[size][1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -972,7 +968,7 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
|
|||
|
||||
mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */
|
||||
PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
|
||||
pdev->image.x, pdev->image.y);
|
||||
pdev->width, pdev->height);
|
||||
pwc_vidioc_fill_fmt(pdev, f);
|
||||
mutex_unlock(&pdev->udevlock);
|
||||
return 0;
|
||||
|
@ -1061,25 +1057,21 @@ static int pwc_enum_framesizes(struct file *file, void *fh,
|
|||
struct pwc_device *pdev = video_drvdata(file);
|
||||
unsigned int i = 0, index = fsize->index;
|
||||
|
||||
if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
|
||||
if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 ||
|
||||
(fsize->pixel_format == V4L2_PIX_FMT_PWC1 &&
|
||||
DEVICE_USE_CODEC1(pdev->type)) ||
|
||||
(fsize->pixel_format == V4L2_PIX_FMT_PWC2 &&
|
||||
DEVICE_USE_CODEC23(pdev->type))) {
|
||||
for (i = 0; i < PSZ_MAX; i++) {
|
||||
if (pdev->image_mask & (1UL << i)) {
|
||||
if (!index--) {
|
||||
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||
fsize->discrete.width = pwc_image_sizes[i].x;
|
||||
fsize->discrete.height = pwc_image_sizes[i].y;
|
||||
return 0;
|
||||
}
|
||||
if (!(pdev->image_mask & (1UL << i)))
|
||||
continue;
|
||||
if (!index--) {
|
||||
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||
fsize->discrete.width = pwc_image_sizes[i][0];
|
||||
fsize->discrete.height = pwc_image_sizes[i][1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (fsize->index == 0 &&
|
||||
((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
|
||||
(fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
|
||||
|
||||
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||
fsize->discrete.width = pdev->abs_max.x;
|
||||
fsize->discrete.height = pdev->abs_max.y;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1092,8 +1084,8 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
|
|||
unsigned int i;
|
||||
|
||||
for (i = 0; i < PSZ_MAX; i++) {
|
||||
if (pwc_image_sizes[i].x == fival->width &&
|
||||
pwc_image_sizes[i].y == fival->height) {
|
||||
if (pwc_image_sizes[i][0] == fival->width &&
|
||||
pwc_image_sizes[i][1] == fival->height) {
|
||||
size = i;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,9 @@
|
|||
#define FEATURE_CODEC1 0x0002
|
||||
#define FEATURE_CODEC2 0x0004
|
||||
|
||||
#define MAX_WIDTH 640
|
||||
#define MAX_HEIGHT 480
|
||||
|
||||
/* Ignore errors in the first N frames, to allow for startup delays */
|
||||
#define FRAME_LOWMARK 5
|
||||
|
||||
|
@ -205,12 +208,6 @@ struct pwc_raw_frame {
|
|||
__u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */
|
||||
} __packed;
|
||||
|
||||
/* structure for transferring x & y coordinates */
|
||||
struct pwc_coord {
|
||||
int x, y; /* guess what */
|
||||
int size; /* size, or offset */
|
||||
};
|
||||
|
||||
/* intermediate buffers with raw data from the USB cam */
|
||||
struct pwc_frame_buf
|
||||
{
|
||||
|
@ -233,7 +230,6 @@ struct pwc_device
|
|||
int type;
|
||||
int release; /* release number */
|
||||
int features; /* feature bits */
|
||||
char serial[30]; /* serial number (string) */
|
||||
|
||||
/*** Video data ***/
|
||||
struct file *capt_file; /* file doing video capture */
|
||||
|
@ -286,10 +282,7 @@ struct pwc_device
|
|||
* a gray or black border. view_min <= image <= view <= view_max;
|
||||
*/
|
||||
int image_mask; /* supported sizes */
|
||||
struct pwc_coord view_min, view_max; /* minimum and maximum view */
|
||||
struct pwc_coord abs_max; /* maximum supported size */
|
||||
struct pwc_coord image, view; /* image and viewport size */
|
||||
struct pwc_coord offset; /* offset of the viewport */
|
||||
int width, height; /* current resolution */
|
||||
|
||||
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
||||
struct input_dev *button_dev; /* webcam snapshot button input */
|
||||
|
@ -364,9 +357,9 @@ int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file);
|
|||
|
||||
/** Functions in pwc-misc.c */
|
||||
/* sizes in pixels */
|
||||
extern const struct pwc_coord pwc_image_sizes[PSZ_MAX];
|
||||
extern const int pwc_image_sizes[PSZ_MAX][2];
|
||||
|
||||
int pwc_decode_size(struct pwc_device *pdev, int width, int height);
|
||||
int pwc_get_size(struct pwc_device *pdev, int width, int height);
|
||||
void pwc_construct(struct pwc_device *pdev);
|
||||
|
||||
/** Functions in pwc-ctrl.c */
|
||||
|
|
Loading…
Reference in a new issue