Commit f89950d3 authored by Mike Isely's avatar Mike Isely Committed by Greg Kroah-Hartman

V4L: pvrusb2: Limit hor res for 24xxx devices

Currently it is not understood how to properly control the horizontal
capture resolution on 24xxx devices.  The pvrusb2 driver is doing
everything it should (pass resolution paramter(s) to cx2341x and
cx25840 modules) but for some reason the result is corrupted video if
any resolution other than 720 is used.  This patch causes the driver
to only permit a horizontal resolution of 720 to be used on 24xxx
devices.  Even if the app requests something else, the driver will
force the resolution back to 720.  This patch still allows full
control of the resolution for 29xxx devices.
Signed-off-by: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMichael Krufky <mkrufky@linuxtv.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent cd219de0
......@@ -43,12 +43,17 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
if (cptr->info->type == pvr2_ctl_bitmask) {
mask &= cptr->info->def.type_bitmask.valid_bits;
} else if (cptr->info->type == pvr2_ctl_int) {
if (val < cptr->info->def.type_int.min_value) {
break;
int lim;
lim = cptr->info->def.type_int.min_value;
if (cptr->info->get_min_value) {
cptr->info->get_min_value(cptr,&lim);
}
if (val > cptr->info->def.type_int.max_value) {
break;
if (val < lim) break;
lim = cptr->info->def.type_int.max_value;
if (cptr->info->get_max_value) {
cptr->info->get_max_value(cptr,&lim);
}
if (val > lim) break;
} else if (cptr->info->type == pvr2_ctl_enum) {
if (val >= cptr->info->def.type_enum.count) {
break;
......@@ -91,7 +96,9 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
int ret = 0;
if (!cptr) return 0;
LOCK_TAKE(cptr->hdw->big_lock); do {
if (cptr->info->type == pvr2_ctl_int) {
if (cptr->info->get_max_value) {
cptr->info->get_max_value(cptr,&ret);
} else if (cptr->info->type == pvr2_ctl_int) {
ret = cptr->info->def.type_int.max_value;
}
} while(0); LOCK_GIVE(cptr->hdw->big_lock);
......@@ -105,7 +112,9 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
int ret = 0;
if (!cptr) return 0;
LOCK_TAKE(cptr->hdw->big_lock); do {
if (cptr->info->type == pvr2_ctl_int) {
if (cptr->info->get_min_value) {
cptr->info->get_min_value(cptr,&ret);
} else if (cptr->info->type == pvr2_ctl_int) {
ret = cptr->info->def.type_int.min_value;
}
} while(0); LOCK_GIVE(cptr->hdw->big_lock);
......
......@@ -107,6 +107,8 @@ struct pvr2_ctl_info {
/* Control's implementation */
pvr2_ctlf_get_value get_value; /* Get its value */
pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */
pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */
pvr2_ctlf_set_value set_value; /* Set its value */
pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */
pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */
......
......@@ -362,6 +362,30 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
return 0;
}
#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp)
{
/* If we're dealing with a 24xxx device, force the horizontal
maximum to be 720 no matter what, since we can't get the device
to work properly with any other value. Otherwise just return
the normal value. */
*vp = cptr->info->def.type_int.max_value;
if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
return 0;
}
static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp)
{
/* If we're dealing with a 24xxx device, force the horizontal
minimum to be 720 no matter what, since we can't get the device
to work properly with any other value. Otherwise just return
the normal value. */
*vp = cptr->info->def.type_int.min_value;
if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
return 0;
}
#endif
static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
{
return cptr->hdw->enc_stale != 0;
......@@ -720,6 +744,12 @@ static const struct pvr2_ctl_info control_defs[] = {
.default_value = 720,
DEFREF(res_hor),
DEFINT(320,720),
#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
/* Hook in check for clamp on horizontal resolution in
order to avoid unsolved problem involving cx25840. */
.get_max_value = ctrl_hres_max_get,
.get_min_value = ctrl_hres_min_get,
#endif
},{
.desc = "Vertical capture resolution",
.name = "resolution_ver",
......
......@@ -456,18 +456,26 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
ret = 0;
switch(vf->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
int lmin,lmax;
struct pvr2_ctrl *hcp,*vcp;
int h = vf->fmt.pix.height;
int w = vf->fmt.pix.width;
hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
if (h < 200) {
h = 200;
} else if (h > 625) {
h = 625;
lmin = pvr2_ctrl_get_min(hcp);
lmax = pvr2_ctrl_get_max(hcp);
if (w < lmin) {
w = lmin;
} else if (w > lmax) {
w = lmax;
}
if (w < 320) {
w = 320;
} else if (w > 720) {
w = 720;
lmin = pvr2_ctrl_get_min(vcp);
lmax = pvr2_ctrl_get_max(vcp);
if (h < lmin) {
h = lmin;
} else if (h > lmax) {
h = lmax;
}
memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
......@@ -476,14 +484,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
vf->fmt.pix.height = h;
if (cmd == VIDIOC_S_FMT) {
pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,
PVR2_CID_HRES),
vf->fmt.pix.width);
pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,
PVR2_CID_VRES),
vf->fmt.pix.height);
pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
}
} break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
......
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