V4L/DVB (4926): Fix USBVision handling of VIDIOC_QUERYCTRL

There's a better (and recommended) way for handling VIDIOC_QUERYCTRL.

This patch will fix the issue where the hardware control values were
invalid and stops the SAA7115 module from complaining about invalid values.

saa7115 4-0024: invalid brightness setting 32768
saa7115 4-0024: invalid contrast setting 49152
saa7115 4-0024: invalid hue setting 32768
saa7115 4-0024: invalid saturation setting 32768

Signed-off-by: Dwaine Garden <dwainegarden@rogers.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Dwaine Garden
2006-12-04 08:31:11 -03:00
committed by Mauro Carvalho Chehab
parent cc9e595a58
commit 18d8a4540c

View File

@@ -427,14 +427,14 @@ enum {
};
static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
{ 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" },
{ 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" },
{ 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" },
{ 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" },
{ 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" },
{ 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" },
{ 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 !
{ 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
{ 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" },
{ 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" },
{ 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" },
{ 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" },
{ 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" },
{ 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" },
{ 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 !
{ 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
};
@@ -448,11 +448,6 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer
static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE;
static int init_brightness = 128; // Initalize the brightness of the video device
static int init_contrast = 192; // Initalize the contrast of the video device
static int init_saturation = 128; // Initalize the staturation mode of the video device
static int init_hue = 128; // Initalize the Hue settings of the video device
// Function prototypes
static int usbvision_restart_isoc(struct usb_usbvision *usbvision);
static int usbvision_begin_streaming(struct usb_usbvision *usbvision);
@@ -488,8 +483,8 @@ static int adjustCompression = 1; // Set the compression to be adaptive
static int dga = 1; // Set the default Direct Graphic Access
static int PowerOnAtOpen = 1; // Set the default device to power on at startup
static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently.
static int video_nr = -1; // Sequential Number of Video Device
static int radio_nr = -1; // Sequential Number of Radio Device
static int video_nr = -1; // Sequential Number of Video Device
static int radio_nr = -1; // Sequential Number of Radio Device
static int vbi_nr = -1; // Sequential Number of VBI Device
static char *CustomDevice=NULL; // Set as nothing....
@@ -518,7 +513,7 @@ MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White ou
MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...)
MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...)
MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...)
MODULE_PARM(CustomDevice, "s"); // .... CustomDevice
MODULE_PARM(CustomDevice, "s"); // .... CustomDevice
#endif
MODULE_PARM_DESC(flags, " Set the default Overlay Display mode of the device driver. Default: 0 (Off)");
@@ -549,8 +544,8 @@ static unsigned int autoload = 0;
/****************************************************************************************/
/* SYSFS Code - Copied from the stv680.c usb module. */
/* Device information is located at /sys/class/video4linux/video0 */
/* SYSFS Code - Copied from the stv680.c usb module. */
/* Device information is located at /sys/class/video4linux/video0 */
/* Device parameters information is located at /sys/module/usbvision */
/* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */
/****************************************************************************************/
@@ -1195,9 +1190,9 @@ void usbvision_osd_stats(struct usb_usbvision *usbvision,
*
* Parameters:
* fullframe: if TRUE then entire frame is filled, otherwise the procedure
* continues from the current scanline.
* continues from the current scanline.
* pmode 0: fill the frame with solid blue color (like on VCR or TV)
* 1: Draw a colored grid
* 1: Draw a colored grid
*
*/
void usbvision_testpattern(struct usb_usbvision *usbvision, int fullframe,
@@ -1622,13 +1617,13 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision,
if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
(frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) )
{ // this is a planar format
//... v4l2_linesize not used here.
//... v4l2_linesize not used here.
f = frame->data + (frame->width * frame->curline);
} else
f = frame->data + (frame->v4l2_linesize * frame->curline);
if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers
// get base of u and b planes add halfoffset
// get base of u and b planes add halfoffset
u = frame->data
+ imageSize
@@ -1637,7 +1632,7 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision,
} else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){
v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ;
v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ;
u = v + (imageSize >>2) ;
}
}
@@ -1687,7 +1682,7 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision,
return ParseState_NextFrame;
}
bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
clipmask_index = frame->curline * MAX_FRAME_WIDTH;
scratch_get(usbvision, StripData, StripLen);
@@ -1781,10 +1776,10 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision,
clipmask_index++;
}
/* Deal with non-integer no. of bytes for YUV420P */
if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 )
*pcopylen += frame->v4l2_linesize;
else
*pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1;
if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 )
*pcopylen += frame->v4l2_linesize;
else
*pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1;
frame->curline += 1;
@@ -1846,7 +1841,7 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision
/* Make sure there's enough data for the entire line */
/* In this mode usbvision transfer 3 bytes for every 2 pixels */
/* I need two lines to decode the color */
bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
clipmask_even_index = frame->curline * MAX_FRAME_WIDTH;
clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH;
@@ -2276,7 +2271,7 @@ static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs)
urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0;
}
urb->status = 0;
urb->status = 0;
urb->dev = usbvision->dev;
errCode = usb_submit_urb (urb, GFP_ATOMIC);
@@ -2562,9 +2557,9 @@ static int attach_inform(struct i2c_client *client)
}
if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) {
tun_addr.mode_mask = T_ANALOG_TV;
tun_addr.type = usbvision->tuner_type;
tun_addr.addr = ADDR_UNSET;
client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
tun_addr.type = usbvision->tuner_type;
tun_addr.addr = ADDR_UNSET;
client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->input.index);
}
@@ -2733,7 +2728,7 @@ static int usbvision_i2c_write(void *data, unsigned char addr, char *buf,
int retval;
int wrcount = 0;
int count;
int maxLen = 4;
int maxLen = 4;
struct usb_usbvision *usbvision = (struct usb_usbvision *) data;
while (len > 0) {
@@ -2841,7 +2836,7 @@ static int usbvision_init_i2c(struct usb_usbvision *usbvision)
break;
}
if (usbvision_device_data[usbvision->DevModel].Tuner == 1) {
request_module("tuner");
request_module("tuner");
}
}
#endif
@@ -3001,7 +2996,7 @@ static int usbvision_set_output(struct usb_usbvision *usbvision, int width,
}
if (usbvision->input.std & V4L2_STD_625_50) {
frameDrop = frameRate * 32 / 25 - 1;
frameDrop = frameRate * 32 / 25 - 1;
}
else if (usbvision->input.std & V4L2_STD_525_60) {
frameDrop = frameRate * 32 / 30 - 1;
@@ -3042,7 +3037,7 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision)
value[2] = 0x00; // Reg.46 Force intra mode on all new frames
value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force)
value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode.
value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression
value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression
//catched values for NT1004
// value[0] = 0xFF; // Never apply intra mode automatically
@@ -3196,7 +3191,7 @@ static int usbvision_set_input(struct usb_usbvision *usbvision)
dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff;
}
else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) {
/* This changes as the fine sync control changes. Further investigation necessary */
/* This changes as the fine sync control changes. Further investigation necessary */
dvi_yuv_value = 0x06;
}
@@ -3532,7 +3527,7 @@ static void usbvision_stop_isoc(struct usb_usbvision *usbvision)
usb_kill_urb(usbvision->sbuf[bufIdx].urb);
usb_free_urb(usbvision->sbuf[bufIdx].urb);
usbvision->sbuf[bufIdx].urb = NULL;
}
}
PDEBUG(DBG_ISOC, "%s: streaming=0\n", __FUNCTION__);
@@ -3950,7 +3945,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
}
break;
case 1:
vi->type = V4L2_INPUT_TYPE_CAMERA;
vi->type = V4L2_INPUT_TYPE_CAMERA;
if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
strcpy(vi->name, "Green Video Input");
}
@@ -3960,7 +3955,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
vi->std = V4L2_STD_PAL;
break;
case 2:
vi->type = V4L2_INPUT_TYPE_CAMERA;
vi->type = V4L2_INPUT_TYPE_CAMERA;
if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
strcpy(vi->name, "Yellow Video Input");
}
@@ -3970,7 +3965,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
vi->std = V4L2_STD_PAL;
break;
case 3:
vi->type = V4L2_INPUT_TYPE_CAMERA;
vi->type = V4L2_INPUT_TYPE_CAMERA;
strcpy(vi->name, "Red Video Input");
vi->std = V4L2_STD_PAL;
break;
@@ -4008,13 +4003,13 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
}
return 0;
}
case VIDIOC_G_INPUT:
case VIDIOC_G_INPUT:
{
int *input = arg;
*input = usbvision->input.index;
return 0;
}
case VIDIOC_S_INPUT:
case VIDIOC_S_INPUT:
{
int *input = arg;
if ((*input >= usbvision->video_inputs) || (*input < 0) )
@@ -4028,14 +4023,14 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
up(&usbvision->lock);
return 0;
}
case VIDIOC_G_STD:
case VIDIOC_G_STD:
{
v4l2_std_id *std = arg;
*std = usbvision->input.std;
PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%x", (unsigned)*std);
return 0;
}
case VIDIOC_S_STD:
case VIDIOC_S_STD:
{
v4l2_std_id *std = arg;
@@ -4049,7 +4044,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%x", (unsigned)*std);
return 0;
}
case VIDIOC_G_TUNER:
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *vt = arg;
struct v4l2_tuner status;
@@ -4118,55 +4113,35 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
// FIXME: void function ???
return 0;
}
case VIDIOC_QUERYCTRL:
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qc = arg;
switch(qc->id) {
case V4L2_CID_BRIGHTNESS:
case V4L2_CID_HUE:
case V4L2_CID_SATURATION:
case V4L2_CID_CONTRAST:
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_MUTE:
return v4l2_ctrl_query_fill_std(qc);
break;
default:
struct v4l2_queryctrl *ctrl = arg;
int id=ctrl->id;
memset(ctrl,0,sizeof(*ctrl));
ctrl->id=id;
i2c_clients_command(&usbvision->i2c_adap, cmd, arg);
if (ctrl->type)
return 0;
else
return -EINVAL;
}
return 0;
PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type);
}
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = usbvision->brightness;
break;
case V4L2_CID_CONTRAST:
ctrl->value = usbvision->contrast;
break;
case V4L2_CID_SATURATION:
ctrl->value = usbvision->saturation;
break;
case V4L2_CID_HUE:
ctrl->value = usbvision->hue;
break;
case V4L2_CID_AUDIO_VOLUME:
/* ctrl->value = usbvision->volume; */
break;
case V4L2_CID_AUDIO_MUTE:
ctrl->value = usbvision->AudioMute;
break;
default:
return -EINVAL;
}
PDEBUG(DBG_IOCTL, "VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
return 0;
}
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value);
call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
return 0;
@@ -4213,7 +4188,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
vb->sequence = usbvision->frame_num;
return 0;
}
case VIDIOC_QBUF: // VIDIOCMCAPTURE + VIDIOCSYNC
case VIDIOC_QBUF: // VIDIOCMCAPTURE + VIDIOCSYNC
{
struct v4l2_buffer *vb = arg;
struct usbvision_frame *frame;
@@ -4323,7 +4298,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
up(&usbvision->lock);
return 0;
}
case VIDIOC_G_FBUF:
case VIDIOC_G_FBUF:
{
struct v4l2_framebuffer *vb = arg;
@@ -4417,7 +4392,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
vf->fmt.win.w.left, vf->fmt.win.w.top, vf->fmt.win.w.width, vf->fmt.win.w.height, vf->fmt.win.chromakey, vf->fmt.win.clipcount);
return 0;
}
case VIDIOC_S_FMT:
case VIDIOC_S_FMT:
{
struct v4l2_format *vf = arg;
struct v4l2_clip *vc=NULL;
@@ -4672,7 +4647,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
while (size > 0) {
// Really ugly....
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) //Compatibility for 2.6.10+ kernels
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) //Compatibility for 2.6.10+ kernels
page = vmalloc_to_pfn((void *)pos);
if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
return -EAGAIN;
@@ -4791,7 +4766,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
/***************************
* V4L2 IOCTLs *
***************************/
case VIDIOC_QUERYCAP:
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *vc=arg;
memset(vc, 0, sizeof(struct v4l2_capability));
@@ -4803,7 +4778,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
PDEBUG(DBG_RIO, "%s: VIDIOC_QUERYCAP", __FUNCTION__);
return 0;
}
case VIDIOC_QUERYCTRL:
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qc = arg;
switch(qc->id)
@@ -4817,7 +4792,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
}
return 0;
}
case VIDIOC_G_CTRL:
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
PDEBUG(DBG_IOCTL, "VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
@@ -4833,7 +4808,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
}
return 0;
}
case VIDIOC_S_CTRL:
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
@@ -4841,7 +4816,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
PDEBUG(DBG_RIO, "%s: VIDIOC_S_CTRL id=%x value=%x", __FUNCTION__,ctrl->id,ctrl->value);
return 0;
}
case VIDIOC_G_TUNER:
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *vt = arg;
@@ -4862,7 +4837,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
PDEBUG(DBG_RIO, "%s: VIDIOC_G_TUNER signal=%d", __FUNCTION__, vt->signal);
return 0;
}
case VIDIOC_S_TUNER:
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *vt = arg;
@@ -4873,7 +4848,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
PDEBUG(DBG_RIO, "%s: VIDIOC_S_TUNER", __FUNCTION__);
return 0;
}
case VIDIOC_G_AUDIO:
case VIDIOC_G_AUDIO:
{
struct v4l2_audio *va = arg;
memset(va,0, sizeof(va));
@@ -4882,7 +4857,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO");
return 0;
}
case VIDIOC_S_AUDIO:
case VIDIOC_S_AUDIO:
{
struct v4l2_audio *v = arg;
if(v->index) {
@@ -4892,7 +4867,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
// FIXME: void function ???
return 0;
}
case VIDIOC_G_FREQUENCY:
case VIDIOC_G_FREQUENCY:
{
struct v4l2_frequency *freq = arg;
freq->tuner = 0; // Only one tuner
@@ -4901,7 +4876,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
PDEBUG(DBG_RIO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
return 0;
}
case VIDIOC_S_FREQUENCY:
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *freq = arg;
usbvision->freq = freq->frequency;
@@ -4913,7 +4888,7 @@ static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
/***************************
* V4L1 IOCTLs *
***************************/
case VIDIOCGCAP:
case VIDIOCGCAP:
{
struct video_capability *vc = arg;
@@ -5229,16 +5204,6 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision)
return;
model = usbvision->DevModel;
RESTRICT_TO_RANGE(init_brightness, 0, 255);
RESTRICT_TO_RANGE(init_contrast, 0, 255);
RESTRICT_TO_RANGE(init_saturation, 0, 255);
RESTRICT_TO_RANGE(init_hue, 0, 255);
usbvision->saturation = init_saturation << 8;
usbvision->hue = init_hue << 8;
usbvision->brightness = init_brightness << 8;
usbvision->contrast = init_contrast << 8;
usbvision->depth = 24;
usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24;
@@ -5743,7 +5708,7 @@ void customdevice_process(void)
usbvision_device_data[0].X_Offset;
usbvision_device_data[0].Y_Offset;
usbvision_device_data[0].Dvi_yuv;
usbvision_device_data[0].ModelString;
usbvision_device_data[0].ModelString;
*/
rmspace(parse);