Commit 795e6eb3 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

[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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent a08d2c72
...@@ -460,16 +460,6 @@ Who: Jean Delvare <khali@linux-fr.org> ...@@ -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. What: For VIDIOC_S_FREQUENCY the type field must match the device node's type.
If not, return -EINVAL. If not, return -EINVAL.
When: 3.2 When: 3.2
......
...@@ -102,8 +102,6 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] = ...@@ -102,8 +102,6 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
#include "pwc-nala.h" #include "pwc-nala.h"
}; };
static void pwc_set_image_buffer_size(struct pwc_device *pdev);
/****************************************************************************/ /****************************************************************************/
static int _send_control_msg(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) ...@@ -221,8 +219,9 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
/* Set various parameters */ /* Set various parameters */
pdev->vframes = frames; pdev->vframes = frames;
pdev->valternate = pEntry->alternate; pdev->valternate = pEntry->alternate;
pdev->image = pwc_image_sizes[size]; pdev->width = pwc_image_sizes[size][0];
pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2; pdev->height = pwc_image_sizes[size][1];
pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
if (pEntry->compressed) { if (pEntry->compressed) {
if (pdev->release < 5) { /* 4 fold compression */ if (pdev->release < 5) { /* 4 fold compression */
pdev->vbandlength = 528; pdev->vbandlength = 528;
...@@ -282,12 +281,13 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, ...@@ -282,12 +281,13 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
/* Set various parameters */ /* Set various parameters */
pdev->vframes = frames; pdev->vframes = frames;
pdev->valternate = pChoose->alternate; 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; pdev->vbandlength = pChoose->bandlength;
if (pChoose->bandlength > 0) if (pChoose->bandlength > 0)
pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4; pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
else else
pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
return 0; return 0;
} }
...@@ -339,37 +339,25 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, ...@@ -339,37 +339,25 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
/* All set and go */ /* All set and go */
pdev->vframes = frames; pdev->vframes = frames;
pdev->valternate = pChoose->alternate; 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; pdev->vbandlength = pChoose->bandlength;
if (pdev->vbandlength > 0) if (pdev->vbandlength > 0)
pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
else 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", PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
pdev->frame_size, pdev->vframes, size, pdev->vbandlength); pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
return 0; 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 pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
int frames, int compression) int frames, int compression)
{ {
int ret, size; int ret, size;
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt); PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
size = pwc_decode_size(pdev, width, height); size = pwc_get_size(pdev, width, height);
if (size < 0) {
PWC_DEBUG_MODULE("Could not find suitable size.\n");
return -ERANGE;
}
PWC_TRACE("decode_size = %d.\n", size); PWC_TRACE("decode_size = %d.\n", size);
if (DEVICE_USE_CODEC1(pdev->type)) { if (DEVICE_USE_CODEC1(pdev->type)) {
...@@ -385,12 +373,9 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, ...@@ -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); PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
return ret; return ret;
} }
pdev->view.x = width;
pdev->view.y = height;
pdev->vcompression = compression; pdev->vcompression = compression;
pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; 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 resolution to %dx%d\n", pdev->width, pdev->height);
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);
return 0; return 0;
} }
...@@ -447,34 +432,6 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i ...@@ -447,34 +432,6 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
return ret; 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 pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{ {
int ret; int ret;
......
...@@ -656,10 +656,6 @@ static void DecompressBand23(struct pwc_dec23_private *pdec, ...@@ -656,10 +656,6 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
* *
* Uncompress a pwc23 buffer. * 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 * src: raw data
* dst: image output * dst: image output
*/ */
...@@ -667,7 +663,7 @@ void pwc_dec23_decompress(const struct pwc_device *pwc, ...@@ -667,7 +663,7 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
const void *src, const void *src,
void *dst) void *dst)
{ {
int bandlines_left, stride, bytes_per_block; int bandlines_left, bytes_per_block;
struct pwc_dec23_private *pdec = pwc->decompress_data; struct pwc_dec23_private *pdec = pwc->decompress_data;
/* YUV420P image format */ /* YUV420P image format */
...@@ -678,28 +674,23 @@ void pwc_dec23_decompress(const struct pwc_device *pwc, ...@@ -678,28 +674,23 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
mutex_lock(&pdec->lock); mutex_lock(&pdec->lock);
bandlines_left = pwc->image.y / 4; bandlines_left = pwc->height / 4;
bytes_per_block = pwc->view.x * 4; bytes_per_block = pwc->width * 4;
plane_size = pwc->view.x * pwc->view.y; 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 */ pout_planar_y = dst;
stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; pout_planar_u = dst + plane_size;
pout_planar_u = dst + plane_size + stride; pout_planar_v = dst + plane_size + plane_size / 4;
pout_planar_v = dst + plane_size + plane_size / 4 + stride;
while (bandlines_left--) { while (bandlines_left--) {
DecompressBand23(pwc->decompress_data, DecompressBand23(pwc->decompress_data,
src, src,
pout_planar_y, pout_planar_u, pout_planar_v, pout_planar_y, pout_planar_u, pout_planar_v,
pwc->image.x, pwc->view.x); pwc->width, pwc->width);
src += pwc->vbandlength; src += pwc->vbandlength;
pout_planar_y += bytes_per_block; pout_planar_y += bytes_per_block;
pout_planar_u += pwc->view.x; pout_planar_u += pwc->width;
pout_planar_v += pwc->view.x; pout_planar_v += pwc->width;
} }
mutex_unlock(&pdec->lock); mutex_unlock(&pdec->lock);
} }
...@@ -656,6 +656,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, ...@@ -656,6 +656,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
unsigned int sizes[], void *alloc_ctxs[]) unsigned int sizes[], void *alloc_ctxs[])
{ {
struct pwc_device *pdev = vb2_get_drv_priv(vq); struct pwc_device *pdev = vb2_get_drv_priv(vq);
int size;
if (*nbuffers < MIN_FRAMES) if (*nbuffers < MIN_FRAMES)
*nbuffers = MIN_FRAMES; *nbuffers = MIN_FRAMES;
...@@ -664,7 +665,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, ...@@ -664,7 +665,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
*nplanes = 1; *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; return 0;
} }
...@@ -742,7 +745,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) ...@@ -742,7 +745,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
pwc_camera_power(pdev, 1); pwc_camera_power(pdev, 1);
if (pdev->power_save) { if (pdev->power_save) {
/* Restore video mode */ /* 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); pdev->vframes, pdev->vcompression);
} }
pwc_set_leds(pdev, led_on, led_off); 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 ...@@ -1056,7 +1059,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
} }
pdev->type = type_id; pdev->type = type_id;
pdev->vframes = default_fps; pdev->vframes = default_fps;
strcpy(pdev->serial, serial_number);
pdev->features = features; pdev->features = features;
pwc_construct(pdev); /* set min/max sizes correct */ 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 ...@@ -1119,7 +1121,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pwc_set_leds(pdev, 0, 0); pwc_set_leds(pdev, 0, 0);
/* Setup intial videomode */ /* 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); pdev->vframes, pdev->vcompression);
if (rc) if (rc)
goto err_free_mem; goto err_free_mem;
......
...@@ -27,67 +27,47 @@ ...@@ -27,67 +27,47 @@
#include "pwc.h" #include "pwc.h"
const struct pwc_coord pwc_image_sizes[PSZ_MAX] = const int pwc_image_sizes[PSZ_MAX][2] =
{ {
{ 128, 96, 0 }, /* sqcif */ { 128, 96 }, /* sqcif */
{ 160, 120, 0 }, /* qsif */ { 160, 120 }, /* qsif */
{ 176, 144, 0 }, /* qcif */ { 176, 144 }, /* qcif */
{ 320, 240, 0 }, /* sif */ { 320, 240 }, /* sif */
{ 352, 288, 0 }, /* cif */ { 352, 288 }, /* cif */
{ 640, 480, 0 }, /* vga */ { 640, 480 }, /* vga */
}; };
/* x,y -> PSZ_ */ /* 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; int i;
/* 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;
}
}
/* Find the largest size supported by the camera that fits into the /* Find the largest size supported by the camera that fits into the
requested size. requested size. */
*/ for (i = PSZ_MAX - 1; i >= 0; i--) {
find = -1; if (!(pdev->image_mask & (1 << i)))
continue;
if (pwc_image_sizes[i][0] <= width &&
pwc_image_sizes[i][1] <= height)
return i;
}
/* No mode found, return the smallest mode we have */
for (i = 0; i < PSZ_MAX; i++) { for (i = 0; i < PSZ_MAX; i++) {
if (pdev->image_mask & (1 << i)) { if (pdev->image_mask & (1 << i))
if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height) return i;
find = i;
}
} }
return find;
/* 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) void pwc_construct(struct pwc_device *pdev)
{ {
if (DEVICE_USE_CODEC1(pdev->type)) { 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->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
pdev->vcinterface = 2; pdev->vcinterface = 2;
pdev->vendpoint = 4; pdev->vendpoint = 4;
...@@ -96,13 +76,7 @@ void pwc_construct(struct pwc_device *pdev) ...@@ -96,13 +76,7 @@ void pwc_construct(struct pwc_device *pdev)
} else if (DEVICE_USE_CODEC3(pdev->type)) { } 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->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->vcinterface = 3;
pdev->vendpoint = 5; pdev->vendpoint = 5;
pdev->frame_header_size = TOUCAM_HEADER_SIZE; pdev->frame_header_size = TOUCAM_HEADER_SIZE;
...@@ -110,20 +84,11 @@ void pwc_construct(struct pwc_device *pdev) ...@@ -110,20 +84,11 @@ void pwc_construct(struct pwc_device *pdev)
} else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { } 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->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->vcinterface = 3;
pdev->vendpoint = 4; pdev->vendpoint = 4;
pdev->frame_header_size = 0; pdev->frame_header_size = 0;
pdev->frame_trailer_size = 0; pdev->frame_trailer_size = 0;
} }
pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */ 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 @@ ...@@ -35,7 +35,7 @@
int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
{ {
int n, line, col, stride; int n, line, col;
void *yuv, *image; void *yuv, *image;
u16 *src; u16 *src;
u16 *dsty, *dstu, *dstv; u16 *dsty, *dstu, *dstv;
...@@ -60,35 +60,23 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) ...@@ -60,35 +60,23 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
return 0; 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) { if (pdev->vbandlength == 0) {
/* Uncompressed mode. /* 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 * We do some byte shuffling here to go from the
* native format to YUV420P. * native format to YUV420P.
*/ */
src = (u16 *)yuv; 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 */ for (line = 0; line < pdev->height; line++) {
stride = pdev->view.x * pdev->offset.y + pdev->offset.x; for (col = 0; col < pdev->width; col += 4) {
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) {
*dsty++ = *src++; *dsty++ = *src++;
*dsty++ = *src++; *dsty++ = *src++;
if (line & 1) if (line & 1)
...@@ -96,11 +84,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) ...@@ -96,11 +84,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
else else
*dstu++ = *src++; *dstu++ = *src++;
} }
dsty += stride;
if (line & 1)
dstv += (stride >> 1);
else
dstu += (stride >> 1);
} }
return 0; return 0;
...@@ -122,6 +105,3 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) ...@@ -122,6 +105,3 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
} }
return 0; return 0;
} }
/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
...@@ -398,8 +398,8 @@ int pwc_init_controls(struct pwc_device *pdev) ...@@ -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) 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)); memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
f->fmt.pix.width = pdev->view.x; f->fmt.pix.width = pdev->width;
f->fmt.pix.height = pdev->view.y; f->fmt.pix.height = pdev->height;
f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.field = V4L2_FIELD_NONE;
if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) { if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
f->fmt.pix.pixelformat = 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 ...@@ -429,6 +429,8 @@ static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_forma
/* ioctl(VIDIOC_TRY_FMT) */ /* ioctl(VIDIOC_TRY_FMT) */
static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
{ {
int size;
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
return -EINVAL; return -EINVAL;
...@@ -455,15 +457,9 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) ...@@ -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) size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
f->fmt.pix.width = pdev->view_max.x; f->fmt.pix.width = pwc_image_sizes[size][0];
else if (f->fmt.pix.width < pdev->view_min.x) f->fmt.pix.height = pwc_image_sizes[size][1];
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;
return 0; return 0;
} }
...@@ -972,7 +968,7 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) ...@@ -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 */ mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */
PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", 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); pwc_vidioc_fill_fmt(pdev, f);
mutex_unlock(&pdev->udevlock); mutex_unlock(&pdev->udevlock);
return 0; return 0;
...@@ -1061,25 +1057,21 @@ static int pwc_enum_framesizes(struct file *file, void *fh, ...@@ -1061,25 +1057,21 @@ static int pwc_enum_framesizes(struct file *file, void *fh,
struct pwc_device *pdev = video_drvdata(file); struct pwc_device *pdev = video_drvdata(file);
unsigned int i = 0, index = fsize->index; 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++) { for (i = 0; i < PSZ_MAX; i++) {
if (pdev->image_mask & (1UL << i)) { if (!(pdev->image_mask & (1UL << i)))
if (!index--) { continue;
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; if (!index--) {
fsize->discrete.width = pwc_image_sizes[i].x; fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
fsize->discrete.height = pwc_image_sizes[i].y; fsize->discrete.width = pwc_image_sizes[i][0];
return 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; return -EINVAL;
} }
...@@ -1092,8 +1084,8 @@ static int pwc_enum_frameintervals(struct file *file, void *fh, ...@@ -1092,8 +1084,8 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
unsigned int i; unsigned int i;
for (i = 0; i < PSZ_MAX; i++) { for (i = 0; i < PSZ_MAX; i++) {
if (pwc_image_sizes[i].x == fival->width && if (pwc_image_sizes[i][0] == fival->width &&
pwc_image_sizes[i].y == fival->height) { pwc_image_sizes[i][1] == fival->height) {
size = i; size = i;
break; break;
} }
......
...@@ -107,6 +107,9 @@ ...@@ -107,6 +107,9 @@
#define FEATURE_CODEC1 0x0002 #define FEATURE_CODEC1 0x0002
#define FEATURE_CODEC2 0x0004 #define FEATURE_CODEC2 0x0004
#define MAX_WIDTH 640
#define MAX_HEIGHT 480
/* Ignore errors in the first N frames, to allow for startup delays */ /* Ignore errors in the first N frames, to allow for startup delays */
#define FRAME_LOWMARK 5 #define FRAME_LOWMARK 5
...@@ -205,12 +208,6 @@ struct pwc_raw_frame { ...@@ -205,12 +208,6 @@ struct pwc_raw_frame {
__u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */ __u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */
} __packed; } __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 */ /* intermediate buffers with raw data from the USB cam */
struct pwc_frame_buf struct pwc_frame_buf
{ {
...@@ -233,7 +230,6 @@ struct pwc_device ...@@ -233,7 +230,6 @@ struct pwc_device
int type; int type;
int release; /* release number */ int release; /* release number */
int features; /* feature bits */ int features; /* feature bits */
char serial[30]; /* serial number (string) */
/*** Video data ***/ /*** Video data ***/
struct file *capt_file; /* file doing video capture */ struct file *capt_file; /* file doing video capture */
...@@ -286,10 +282,7 @@ struct pwc_device ...@@ -286,10 +282,7 @@ struct pwc_device
* a gray or black border. view_min <= image <= view <= view_max; * a gray or black border. view_min <= image <= view <= view_max;
*/ */
int image_mask; /* supported sizes */ int image_mask; /* supported sizes */
struct pwc_coord view_min, view_max; /* minimum and maximum view */ int width, height; /* current resolution */
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 */
#ifdef CONFIG_USB_PWC_INPUT_EVDEV #ifdef CONFIG_USB_PWC_INPUT_EVDEV
struct input_dev *button_dev; /* webcam snapshot button input */ 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); ...@@ -364,9 +357,9 @@ int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file);
/** Functions in pwc-misc.c */ /** Functions in pwc-misc.c */
/* sizes in pixels */ /* 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); void pwc_construct(struct pwc_device *pdev);
/** Functions in pwc-ctrl.c */ /** Functions in pwc-ctrl.c */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment