Skip to content

Commit

Permalink
V4L/DVB (5547): Add ENUM_FRAMESIZES and ENUM_FRAMEINTERVALS ioctls
Browse files Browse the repository at this point in the history
This patch add support for the VIDIOC_ENUM_FRAMESIZES and
VIDIOC_ENUM_FRAMEINTERVALS ioctl.
* check if the maximum native framesize for raw mode is correct
* raw mode framerates for all three chipset types

Signed-off-by: Gregor Jasny <[email protected]>
Signed-off-by: Luc Saillard <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
Luc Saillard authored and mchehab committed Apr 27, 2007
1 parent 1de6923 commit 9ee6d78
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 11 deletions.
61 changes: 59 additions & 2 deletions drivers/media/video/pwc/pwc-ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,18 @@ static const char *size2name[PSZ_MAX] =
An alternate value of 0 means this mode is not available at all.
*/

#define PWC_FPS_MAX_NALA 8

struct Nala_table_entry {
char alternate; /* USB alternate setting */
int compressed; /* Compressed yes/no */

unsigned char mode[3]; /* precomputed mode table */
};

static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };

static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
{
#include "pwc-nala.h"
};
Expand Down Expand Up @@ -423,6 +427,59 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
return 0;
}

static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int i;

for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
if (Nala_table[size][i].alternate) {
if (index--==0) return Nala_fps_vector[i];
}
}
return 0;
}

static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int i;

for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
if (Kiara_table[size][i][3].alternate) {
if (index--==0) return Kiara_fps_vector[i];
}
}
return 0;
}

static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int i;

for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
if (Timon_table[size][i][3].alternate) {
if (index--==0) return Timon_fps_vector[i];
}
}
return 0;
}

unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int ret;

if (DEVICE_USE_CODEC1(pdev->type)) {
ret = pwc_get_fps_Nala(pdev, index, size);

} else if (DEVICE_USE_CODEC3(pdev->type)) {
ret = pwc_get_fps_Kiara(pdev, index, size);

} else {
ret = pwc_get_fps_Timon(pdev, index, size);
}

return ret;
}

#define BLACK_Y 0
#define BLACK_U 128
#define BLACK_V 128
Expand Down Expand Up @@ -1343,7 +1400,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
if (ret < 0)
break;
ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
ret = pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
if (ret < 0)
break;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/pwc/pwc-if.c
Original file line number Diff line number Diff line change
Expand Up @@ -1493,7 +1493,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
case 0x0329:
PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
name = "Philips SPC 900NC webcam";
type_id = 720;
type_id = 740;
break;
default:
return -ENODEV;
Expand Down
36 changes: 34 additions & 2 deletions drivers/media/video/pwc/pwc-ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define PWC_IOCTL_H

/* (C) 2001-2004 Nemosoft Unv.
(C) 2004 Luc Saillard ([email protected])
(C) 2004-2006 Luc Saillard ([email protected])
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Expand All @@ -25,7 +25,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

/* This is pwc-ioctl.h belonging to PWC 8.12.1
/* This is pwc-ioctl.h belonging to PWC 10.0.10
It contains structures and defines to communicate from user space
directly to the driver.
*/
Expand All @@ -51,6 +51,9 @@
... the function
*/

#include <linux/types.h>
#include <linux/version.h>


/* Enumeration of image sizes */
#define PSZ_SQCIF 0x00
Expand All @@ -65,6 +68,8 @@
/* The frame rate is encoded in the video_window.flags parameter using
the upper 16 bits, since some flags are defined nowadays. The following
defines provide a mask and shift to filter out this value.
This value can also be passing using the private flag when using v4l2 and
VIDIOC_S_FMT ioctl.
In 'Snapshot' mode the camera freezes its automatic exposure and colour
balance controls.
Expand All @@ -73,6 +78,8 @@
#define PWC_FPS_MASK 0x00FF0000
#define PWC_FPS_FRMASK 0x003F0000
#define PWC_FPS_SNAPSHOT 0x00400000
#define PWC_QLT_MASK 0x03000000
#define PWC_QLT_SHIFT 24


/* structure for transferring x & y coordinates */
Expand Down Expand Up @@ -289,4 +296,29 @@ struct pwc_table_init_buffer {
};
#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer)

/*
* This is private command used when communicating with v4l2.
* In the future all private ioctl will be remove/replace to
* use interface offer by v4l2.
*/

#define V4L2_CID_PRIVATE_SAVE_USER (V4L2_CID_PRIVATE_BASE + 0)
#define V4L2_CID_PRIVATE_RESTORE_USER (V4L2_CID_PRIVATE_BASE + 1)
#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
#define V4L2_CID_PRIVATE_COLOUR_MODE (V4L2_CID_PRIVATE_BASE + 3)
#define V4L2_CID_PRIVATE_AUTOCONTOUR (V4L2_CID_PRIVATE_BASE + 4)
#define V4L2_CID_PRIVATE_CONTOUR (V4L2_CID_PRIVATE_BASE + 5)
#define V4L2_CID_PRIVATE_BACKLIGHT (V4L2_CID_PRIVATE_BASE + 6)
#define V4L2_CID_PRIVATE_FLICKERLESS (V4L2_CID_PRIVATE_BASE + 7)
#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)

struct pwc_raw_frame {
__le16 type; /* type of the webcam */
__le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */
__u8 cmd[4]; /* the four byte of the command (in case of nala,
only the first 3 bytes is filled) */
__u8 rawframe[0]; /* frame_size = H/4*vbandlength */
} __attribute__ ((packed));


#endif
2 changes: 2 additions & 0 deletions drivers/media/video/pwc/pwc-kiara.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
#include "pwc-kiara.h"
#include "pwc-uncompress.h"

const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25, 30 };

const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
{
/* SQCIF */
Expand Down
5 changes: 4 additions & 1 deletion drivers/media/video/pwc/pwc-kiara.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

#include <media/pwc-ioctl.h>

#define PWC_FPS_MAX_KIARA 6

struct Kiara_table_entry
{
char alternate; /* USB alternate interface */
Expand All @@ -37,8 +39,9 @@ struct Kiara_table_entry
unsigned char mode[12]; /* precomputed mode settings for cam */
};

extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][PWC_FPS_MAX_KIARA][4];
extern const unsigned int KiaraRomTable[8][2][16][8];
extern const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA];

#endif

Expand Down
4 changes: 3 additions & 1 deletion drivers/media/video/pwc/pwc-timon.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@

#include "pwc-timon.h"

const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON] = { 5, 10, 15, 20, 25, 30 };

const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4] =
{
/* SQCIF */
{
Expand Down
6 changes: 4 additions & 2 deletions drivers/media/video/pwc/pwc-timon.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

#include <media/pwc-ioctl.h>

#define PWC_FPS_MAX_TIMON 6

struct Timon_table_entry
{
char alternate; /* USB alternate interface */
Expand All @@ -52,9 +54,9 @@ struct Timon_table_entry
unsigned char mode[13]; /* precomputed mode settings for cam */
};

extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
extern const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4];
extern const unsigned int TimonRomTable [16][2][16][8];

extern const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON];

#endif

Expand Down
58 changes: 58 additions & 0 deletions drivers/media/video/pwc/pwc-v4l.c
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,64 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return 0;
}

case VIDIOC_ENUM_FRAMESIZES:
{
struct v4l2_frmsizeenum *fsize = arg;
unsigned int i = 0, index = fsize->index;

if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
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;
}
}
}
} 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;
}

case VIDIOC_ENUM_FRAMEINTERVALS:
{
struct v4l2_frmivalenum *fival = arg;
int size = -1;
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) {
size = i;
break;
}
}

/* TODO: Support raw format */
if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420) {
return -EINVAL;
}

i = pwc_get_fps(pdev, fival->index, size);
if (!i)
return -EINVAL;

fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
fival->discrete.numerator = 1;
fival->discrete.denominator = i;

return 0;
}

default:
return pwc_ioctl(pdev, cmd, arg);
} /* ..switch */
Expand Down
5 changes: 3 additions & 2 deletions drivers/media/video/pwc/pwc.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#define PWC_MINOR 0
#define PWC_EXTRAMINOR 12
#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
#define PWC_VERSION "10.0.12"
#define PWC_VERSION "10.0.13"
#define PWC_NAME "pwc"
#define PFX PWC_NAME ": "

Expand Down Expand Up @@ -85,7 +85,7 @@
#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)

#else /* if ! CONFIG_PWC_DEBUG */
#else /* if ! CONFIG_USB_PWC_DEBUG */

#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
Expand Down Expand Up @@ -287,6 +287,7 @@ void pwc_construct(struct pwc_device *pdev);
/** Functions in pwc-ctrl.c */
/* Request a certain video mode. Returns < 0 if not possible */
extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
/* Calculate the number of bytes per image (not frame) */
extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
Expand Down

0 comments on commit 9ee6d78

Please sign in to comment.