V4L/DVB (12118): pvrusb2: Fix hardware scaling when used with cx25840

The cx25840 module requires that its VBI initialization entry point be
called in order for hardware-scaled video capture to work properly -
even if we don't care about VBI.  Making this behavior even more
subtle is that if the capture resolution is set to 720x480 - which is
the default that the pvrusb2 driver sets up - then the cx25840
bypasses the hardware scaler.  Therefore this problem does not
manifest itself until some other resolution, e.g. 640x480, is tried.
MythTV typically defaults to 640x480 or 480x480, which means that
things break whenever the driver is used with MythTV.

This all has been known for a while (since at least Nov 2006), but
recent changes in the pvrusb2 driver (specifically in regards to
sub-device support) caused this to break again.  VBI initialization
must happen *after* the chip's firmware is loaded, not before.  With
this fix, 24xxx devices work correctly again.

A related fix that is part of this changeset is that now we
re-initialize VBI any time after we issue a reset to the cx25840
driver.  Issuing a chip reset erases the state that the VBI setup
previously did.  Until the HVR-1950 came along this subtlety went
unnoticed, because the pvrusb2 driver previously never issued such a
reset.  But with the HVR-1950 we have to do that reset in order to
correctly transition from digital back to analog mode - and since the
HVR-1950 always starts in digital mode (required for the DVB side to
initialize correctly) then this device has never had a chance to work
correctly in analog mode!  Analog capture on the HVR-1950 has been
broken this *ENTIRE* time.  I had missed it until now because I've
usually been testing at the default 720x480 resolution which does not
require scaling...  What fun.  By re-initializing VBI after a cx25840
chip reset, correct behavior is restored.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Mike Isely 2009-06-20 14:45:52 -03:00 committed by Mauro Carvalho Chehab
parent b34cdc36c4
commit e17d787c51
1 changed files with 31 additions and 24 deletions

View File

@ -1987,6 +1987,34 @@ static unsigned int pvr2_copy_i2c_addr_list(
} }
static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw)
{
/*
Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit of nuttiness
for cx25840 causes that module to correctly set up its video
scaling. This is really a problem in the cx25840 module itself,
but we work around it here. The problem has not been seen in
ivtv because there VBI is supported and set up. We don't do VBI
here (at least not yet) and thus we never attempted to even set
it up.
*/
struct v4l2_format fmt;
if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) {
/* We're not using a cx25840 so don't enable the hack */
return;
}
pvr2_trace(PVR2_TRACE_INIT,
"Module ID %u:"
" Executing cx25840 VBI hack",
hdw->decoder_client_id);
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
video, s_fmt, &fmt);
}
static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
const struct pvr2_device_client_desc *cd) const struct pvr2_device_client_desc *cd)
{ {
@ -2078,30 +2106,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
/* client-specific setup... */ /* client-specific setup... */
switch (mid) { switch (mid) {
case PVR2_CLIENT_ID_CX25840: case PVR2_CLIENT_ID_CX25840:
hdw->decoder_client_id = mid;
{
/*
Mike Isely <isely@pobox.com> 19-Nov-2006 - This
bit of nuttiness for cx25840 causes that module
to correctly set up its video scaling. This is
really a problem in the cx25840 module itself,
but we work around it here. The problem has not
been seen in ivtv because there VBI is supported
and set up. We don't do VBI here (at least not
yet) and thus we never attempted to even set it
up.
*/
struct v4l2_format fmt;
pvr2_trace(PVR2_TRACE_INIT,
"Module ID %u:"
" Executing cx25840 VBI hack",
mid);
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
v4l2_device_call_all(&hdw->v4l2_dev, mid,
video, s_fmt, &fmt);
}
break;
case PVR2_CLIENT_ID_SAA7115: case PVR2_CLIENT_ID_SAA7115:
hdw->decoder_client_id = mid; hdw->decoder_client_id = mid;
break; break;
@ -2202,6 +2206,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
cptr->info->set_value(cptr,~0,cptr->info->default_value); cptr->info->set_value(cptr,~0,cptr->info->default_value);
} }
pvr2_hdw_cx25840_vbi_hack(hdw);
/* Set up special default values for the television and radio /* Set up special default values for the television and radio
frequencies here. It's not really important what these defaults frequencies here. It's not really important what these defaults
are, but I set them to something usable in the Chicago area just are, but I set them to something usable in the Chicago area just
@ -4076,6 +4082,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
if (hdw->decoder_client_id) { if (hdw->decoder_client_id) {
v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
core, reset, 0); core, reset, 0);
pvr2_hdw_cx25840_vbi_hack(hdw);
return 0; return 0;
} }
pvr2_trace(PVR2_TRACE_INIT, pvr2_trace(PVR2_TRACE_INIT,