Here below is a patch for the setup: 
Linux 2.6.29.6, 24xxx device, cx25840 decoder, firmware 2.06.039.

Notes:
1.  The vblank default puts the WSS/625 waveform at line 23 in the 
first halfline of the frame.  The odd field image starts at line 23.5. 
http://www.isely.net/pipermail/pvrusb2/2009-July/002512.html  

2. The M/PAL/525 timing seems an anachronism.  If the top of the frame 
contains a few black lines or if the image is bottom centered, try 
setting ctl_crop_top/cur_val to 6.  

3. An odd value in ctl_crop_top/cur_val swaps the spatial interlacing.  
Useful for fixing badly captured system N tapes.  

4. All is childproof since the cx25840 driver now limits width and 
height.  Read ctl_crop_*/cur_val after write to see what was set.  

Installation:
* The function call layout in v4l2-subdef.h has changed.  Removing  *
* and adding the modules pvrusb2 and cx25840 will crash the system. *
patch, 
make clean && make bzImage && make modules 
&& make install && make modules_install, 
rmmod pvrusb2 cx25840 wm8775 tuner v4l2_common videodev, 
reboot if the above doesn't work,
modprobe pvrusb2

Sat Sep  5 14:08:04 CEST 2009
--- linux-2.6.29.6/drivers/media/video/v4l2-subdev-d.c  2009-07-03 
01:41:20.000000000 +0200
+++ linux-2.6.29.6/drivers/media/video/v4l2-subdev.c    2009-09-03 
18:19:04.000000000 +0200
@@ -64,6 +64,8 @@ int v4l2_subdev_command(struct v4l2_subd
                return v4l2_subdev_call(sd, tuner, g_tuner, arg);
        case VIDIOC_S_STD:
                return v4l2_subdev_call(sd, tuner, s_std, *(v4l2_std_id *)arg);
+       case VIDIOC_G_STD:
+               return v4l2_subdev_call(sd, tuner, g_std, arg);
        case VIDIOC_S_FREQUENCY:
                return v4l2_subdev_call(sd, tuner, s_frequency, arg);
        case VIDIOC_G_FREQUENCY:
@@ -92,6 +94,12 @@ int v4l2_subdev_command(struct v4l2_subd
                return v4l2_subdev_call(sd, video, g_vbi_data, arg);
        case VIDIOC_G_SLICED_VBI_CAP:
                return v4l2_subdev_call(sd, video, g_sliced_vbi_cap, arg);
+        case VIDIOC_CROPCAP:
+               return v4l2_subdev_call(sd, video, cropcap, arg);
+        case VIDIOC_S_CROP:
+               return v4l2_subdev_call(sd, video, s_crop, arg);
+        case VIDIOC_G_CROP:
+               return v4l2_subdev_call(sd, video, g_crop, arg);
        case VIDIOC_S_FMT:
                return v4l2_subdev_call(sd, video, s_fmt, arg);
        case VIDIOC_G_FMT:
--- linux-2.6.29.6/drivers/media/video/cx25840/cx25840-core-d.c 2009-07-03 
01:41:20.000000000 +0200
+++ linux-2.6.29.6/drivers/media/video/cx25840/cx25840-core.c   2009-09-05 
07:50:20.000000000 +0200
@@ -348,35 +348,73 @@ static void cx23885_initialize(struct i2
 
 /* ----------------------------------------------------------------------- */
 
+/* This code allows for seamless autodetect. */
+static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+       struct cx25840_state *state = to_state(sd);
+       v4l2_std_id fmt2id[16]={
+               V4L2_STD_UNKNOWN,   V4L2_STD_NTSC_M,   /*  0, 1, */
+               V4L2_STD_NTSC_M_JP, V4L2_STD_NTSC_443, /*  2, 3, */
+               V4L2_STD_PAL,       V4L2_STD_PAL_M,    /*  4, 5, */
+               V4L2_STD_PAL_N,     V4L2_STD_PAL_Nc,   /*  6, 7, */
+               V4L2_STD_PAL_60,    V4L2_STD_UNKNOWN,  /*  8, 9, */   
+               V4L2_STD_UNKNOWN,   V4L2_STD_UNKNOWN,  /* 10, 11, */   
+               V4L2_STD_SECAM,     V4L2_STD_UNKNOWN,  /* 12, 13 */
+               V4L2_STD_UNKNOWN,   V4L2_STD_UNKNOWN   /* 14, 15 */
+       };
+       v4l2_std_id res;
+
+       res=state->std;
+       if(res == V4L2_STD_UNKNOWN) { /* unset or auto: read from decoder */
+               u8 fmt;
+               struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+               /* check VID_FMT_SEL first */
+               fmt = cx25840_read(client, 0x400) & 0xf;
+               if (!fmt) /* set to autodetect: check AFD_FMT_STAT if  */
+                 fmt = cx25840_read(client, 0x40d) & 0xf;
+
+               res=fmt2id[fmt];
+               
+               if(res == V4L2_STD_NTSC_M
+                  && !state->is_cx25836 && cx25840_read(client, 0x805) == 2)
+                 res=V4L2_STD_NTSC_M_KR;
+       }
+       *std=res;
+
+       return 0;
+}
+
 void cx25840_std_setup(struct i2c_client *client)
 {
        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
-       v4l2_std_id std = state->std;
+       v4l2_std_id std;
        int hblank, hactive, burst, vblank, vactive, sc;
        int vblank656, src_decimation;
        int luma_lpf, uv_lpf, comb;
        u32 pll_int, pll_frac, pll_post;
 
+       cx25840_g_std(i2c_get_clientdata(client), &std);
+
        /* datasheet startup, step 8d */
        if (std & ~V4L2_STD_NTSC)
                cx25840_write(client, 0x49f, 0x11);
        else
                cx25840_write(client, 0x49f, 0x14);
 
+       src_decimation = 543;
        if (std & V4L2_STD_625_50) {
-               hblank = 132;
+               hblank = 136; /* 132 */
                hactive = 720;
                burst = 93;
-               vblank = 36;
+               vblank = 34;
                vactive = 580;
-               vblank656 = 40;
-               src_decimation = 0x21f;
                luma_lpf = 2;
 
                if (std & V4L2_STD_SECAM) {
                        uv_lpf = 0;
                        comb = 0;
-                       sc = 0x0a425f;
+                       sc = 672351;  /* 0x0a425f */
                } else if (std == V4L2_STD_PAL_Nc) {
                        uv_lpf = 1;
                        comb = 0x20;
@@ -384,37 +422,34 @@ void cx25840_std_setup(struct i2c_client
                } else {
                        uv_lpf = 1;
                        comb = 0x20;
-                       sc = 688739;
+                       sc = 688739;  /* 0x0a8263 */
                }
        } else {
-               hactive = 720;
                hblank = 122;
+               hactive = 720;
                vactive = 487;
                luma_lpf = 1;
                uv_lpf = 1;
 
-               src_decimation = 0x21f;
                if (std == V4L2_STD_PAL_60) {
                        vblank = 26;
-                       vblank656 = 26;
                        burst = 0x5b;
                        luma_lpf = 2;
                        comb = 0x20;
                        sc = 688739;
                } else if (std == V4L2_STD_PAL_M) {
                        vblank = 20;
-                       vblank656 = 24;
                        burst = 0x61;
                        comb = 0x20;
                        sc = 555452;
                } else {
                        vblank = 26;
-                       vblank656 = 26;
                        burst = 0x5b;
                        comb = 0x66;
                        sc = 556063;
                }
        }
+       vblank656 = vblank+4;
 
        /* DEBUG: Displays configured PLL frequency */
        pll_int = cx25840_read(client, 0x108);
@@ -446,8 +481,8 @@ void cx25840_std_setup(struct i2c_client
 
                v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
                        "vblank %i, vactive %i, vblank656 %i, src_dec %i, "
-                       "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, "
-                       "sc 0x%06x\n",
+                       "burst %i, luma_lpf %i, uv_lpf %i, comb 0x%02x, "
+                       "sc %i\n",
                        hblank, hactive, vblank, vactive, vblank656,
                        src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
        }
@@ -491,20 +526,24 @@ void cx25840_std_setup(struct i2c_client
                cx25840_write(client, 0x47f, 0x00);
                state->vbi_line_offset = 8;
        }
+       /* Alignment test: force the use of vblank656 VIP_OPT_AL */
+       /* cx25840_write(client, 0x406, 0x17); */
 }
 
 /* ----------------------------------------------------------------------- */
 
 static void input_change(struct i2c_client *client)
 {
-       struct cx25840_state *state = to_state(i2c_get_clientdata(client));
-       v4l2_std_id std = state->std;
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct cx25840_state *state = to_state(sd);
+       v4l2_std_id std;
+
+       cx25840_g_std(sd, &std);
 
        /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
        if (std & V4L2_STD_SECAM) {
                cx25840_write(client, 0x402, 0);
-       }
-       else {
+       } else {
                cx25840_write(client, 0x402, 0x04);
                cx25840_write(client, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 
0x11);
        }
@@ -711,6 +750,7 @@ static int set_v4lstd(struct i2c_client 
                cx25840_and_or(client, 0x47b, ~6, 0);
        }
        cx25840_and_or(client, 0x400, ~0xf, fmt);
+       if(!fmt) pal_m=2;
        cx25840_and_or(client, 0x403, ~0x3, pal_m);
        cx25840_std_setup(client);
        if (!state->is_cx25836)
@@ -720,6 +760,191 @@ static int set_v4lstd(struct i2c_client 
 
 /* ----------------------------------------------------------------------- */
 
+struct cdefst {
+  int hblank, hactive, htotal;       /* per line, unit = 1 dot */
+  int vblank, vactive, vtotal, vpre; /* per field, unit = 1 halfline */
+  int doth, dotv;                /* relative size dot: horizontal, vertical */
+};
+static struct cdefst *cdefaulttiming(v4l2_std_id std) 
+{
+  static struct cdefst cdef525={  122, 720, 858,  26, 487, 525, 7,  10, 11 };
+  static struct cdefst cdef525m={ 122, 720, 858,  20, 487, 525, 7,  10, 11 };
+  static struct cdefst cdef625={  136, 720, 864,  34, 580, 625, 4,  59, 54 };
+
+  if(std & V4L2_STD_625_50) return &cdef625;
+
+  if(std == V4L2_STD_PAL_M) return &cdef525m;
+
+  return &cdef525; 
+}
+
+static int min_vblank=2;  /* min vblank delay 2 halfline */
+static int cropcap_origin(struct v4l2_subdev *sd, v4l2_std_id *cstd, struct 
cdefst **cdef, struct v4l2_rect *bounds) 
+{
+       v4l2_std_id std;
+       struct cdefst *def;
+
+       cx25840_g_std(sd, &std);
+       if(cstd) *cstd=std;
+
+       def=cdefaulttiming(std);
+       if(cdef) *cdef=def;
+
+       if(bounds) {
+         bounds->left=4-def->hblank;             /* hblank delay >=4 dot */
+         bounds->width=def->htotal-2;            /* EAV bt.656 */
+         bounds->top=min_vblank-def->vblank;     /* vblank delay >=2h */
+         bounds->height=def->vtotal-2-min_vblank;/* field_sync + min_vblank */
+       }
+
+       return 0;
+}
+
+static int cx25840_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cap) 
+{
+       v4l2_std_id std;
+       struct cdefst *def;
+
+       if(cap->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cropcap_origin(sd, &std, &def, &cap->bounds);
+
+       cap->defrect.left=0;
+       cap->defrect.width=def->hactive;
+       cap->defrect.top=0;
+       cap->defrect.height=def->vactive-def->vpre;
+
+       cap->pixelaspect.numerator=def->dotv;
+       cap->pixelaspect.denominator=def->doth;
+
+       return 0;
+}
+
+/* base    [7:0]=blank_cnt_low 
+ * base+1  [7:4]=active_cnt_low  [3:2]=ss  [1:0]=blank_cnt_high
+ * base+2  [7:6]=rr  [5:0]=active_cnt_high
+ */
+static int bsa_read(struct i2c_client *client, int base, int *pbl, int *psav, 
int *pact) 
+{
+       int save, blank, active;
+
+       blank = cx25840_read(client, base);
+       save = cx25840_read(client, base+1);
+       blank |= ((save & 3) << 8);
+       active = ((save & 0xf0) >> 4) 
+         | ((cx25840_read(client, base+2) & 0x3f) << 4);
+
+       if(pbl) *pbl=blank;
+       if(psav) *psav=save;
+       if(pact) *pact=active;
+       return 0;
+}
+
+static int bsa_write(struct i2c_client *client, int base, int blank, int save, 
int active) 
+{
+       int snew;
+
+       cx25840_write(client, base, blank & 0xff);
+       snew = (save & 0x0c) | ((active & 0xf) << 4) | ((blank >> 8) & 3);
+       cx25840_write(client, base+1, snew);
+       cx25840_write(client, base+2, active >> 4);
+       return 0;
+}
+
+static int cx25840_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       v4l2_std_id std;
+       struct cdefst *def;
+       int hblank, hactive;
+       int vblank, vactive;
+
+       if(crop->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cropcap_origin(sd, &std, &def, NULL);
+
+       bsa_read(client, 0x470, &hblank, NULL, &hactive);
+       crop->c.left = hblank-def->hblank;
+       crop->c.width = hactive;
+
+       bsa_read(client, 0x474, &vblank, NULL, &vactive);
+       crop->c.top = vblank-def->vblank;
+       crop->c.height = vactive-def->vpre;
+
+       return 0;
+}
+
+static int cx25840_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       v4l2_std_id std;
+       struct cdefst *def;
+       struct v4l2_rect b, c;
+       int bleftend, btopend, hwidthmax, vheightmax;
+       int hbnew, hanew, hsave, hblank, hactive;
+       int vbnew, vbnew656, vanew, vsave, vblank, vblank656, vactive;
+
+       if(crop->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cropcap_origin(sd, &std, &def, &b);
+       c=crop->c;
+
+       if(c.width < 2 || c.height<2) {
+               v4l_err(client, "invalid crop=%d:%d:%d:%d\n", c.width, 
+                       c.height, c.left, c.top);
+               return -ERANGE;
+       }
+
+       hwidthmax=def->htotal-16;
+       if(c.width > hwidthmax) c.width=hwidthmax;
+       
+       vheightmax=def->vtotal-def->vpre-min_vblank;
+       if(c.height > vheightmax) c.height=vheightmax;
+
+       /* An odd value for c.top swaps spatial interlacing.  Not enforced 
+        * since VHS tapes with incorrect interlacing exist. 
+        */
+
+       bleftend=b.left+b.width;
+       if(c.left < b.left || c.left+c.width > bleftend) {
+               v4l_err(client, "invalid horizontal crop %d %d\n", 
+                       crop->c.left, crop->c.width);
+               return -ERANGE;
+       }
+       hbnew=c.left+def->hblank;
+       hanew=c.width;
+
+       btopend=b.top+b.height;
+       if(c.top < b.top || c.top+c.height > b.top+b.height) {
+               v4l_err(client, "invalid vertical crop %d %d\n", 
+                       crop->c.top, crop->c.height);
+               return -ERANGE;
+       }
+       vbnew=c.top+def->vblank;
+       vbnew656=vbnew+4;
+       vanew=c.height+def->vpre;
+       //vbnew=34;
+
+       bsa_read(client, 0x470, &hblank, &hsave, &hactive);
+       bsa_write(client, 0x470, hbnew, hsave, hanew);
+       v4l_dbg(1, cx25840_debug, client, "hblank=%i->%i hactive=%i->%i\n", 
+               hblank, hbnew, hactive, hanew);
+
+       bsa_read(client, 0x474, &vblank, &vsave, &vactive);
+       vblank656 = cx25840_read(client, 0x477);
+       bsa_write(client, 0x474, vbnew, vsave, vanew);
+       cx25840_write(client, 0x477, vbnew656 & 0xff);  /* XXX at 256 */
+       v4l_dbg(1, cx25840_debug, client, "vblank=%i->%i vactive=%i->%i"
+               " vblank656=%i->%i\n", vblank,vbnew, vactive,vanew, 
+               vblank656,vbnew656);
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
 static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
        struct cx25840_state *state = to_state(sd);
@@ -844,7 +1069,7 @@ static int cx25840_s_fmt(struct v4l2_sub
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct v4l2_pix_format *pix;
        int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
-       int is_50Hz = !(state->std & V4L2_STD_525_60);
+       int is_50Hz = state->std & V4L2_STD_625_50;
 
        switch (fmt->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -1272,14 +1497,16 @@ static int cx25840_g_tuner(struct v4l2_s
 {
        struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u8 vpres = cx25840_read(client, 0x40e) & 0x20;
+       u8 vpres = cx25840_read(client, 0x40e);
        u8 mode;
-       int val = 0;
+       int signal, val = 0;
 
        if (state->radio)
                return 0;
 
-       vt->signal = vpres ? 0xffff : 0x0;
+       signal= vpres & 0x7f;
+       if(vpres & 0x20) signal|= 0xff80;
+       vt->signal = signal;
        if (state->is_cx25836)
                return 0;
 
@@ -1382,6 +1609,7 @@ static int cx25840_log_status(struct v4l
 
 static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
+       struct v4l2_subdev *sd;
        /* ignore this command */
        if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG)
                return 0;
@@ -1389,8 +1617,9 @@ static int cx25840_command(struct i2c_cl
        /* Old-style drivers rely on initialization on first use, so
           call the init whenever a command is issued to this driver.
           New-style drivers using v4l2_subdev should call init explicitly. */
-       cx25840_init(i2c_get_clientdata(client), 0);
-       return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+       sd = i2c_get_clientdata(client);
+       cx25840_init(sd, 0);
+       return v4l2_subdev_command(sd, cmd, arg);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1412,6 +1641,7 @@ static const struct v4l2_subdev_core_ops
 static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = {
        .s_frequency = cx25840_s_frequency,
        .s_std = cx25840_s_std,
+       .g_std = cx25840_g_std,
        .s_radio = cx25840_s_radio,
        .g_tuner = cx25840_g_tuner,
        .s_tuner = cx25840_s_tuner,
@@ -1424,6 +1654,9 @@ static const struct v4l2_subdev_audio_op
 
 static const struct v4l2_subdev_video_ops cx25840_video_ops = {
        .s_routing = cx25840_s_video_routing,
+       .cropcap = cx25840_cropcap,
+       .g_crop = cx25840_g_crop,
+       .s_crop = cx25840_s_crop,
        .g_fmt = cx25840_g_fmt,
        .s_fmt = cx25840_s_fmt,
        .decode_vbi_line = cx25840_decode_vbi_line,
--- linux-2.6.29.6/drivers/media/video/pvrusb2/pvrusb2-hdw-d.c  2009-07-03 
01:41:20.000000000 +0200
+++ linux-2.6.29.6/drivers/media/video/pvrusb2/pvrusb2-hdw.c    2009-09-05 
04:59:59.000000000 +0200
@@ -450,31 +450,35 @@ static int ctrl_cropt_max_get(struct pvr
        return 0;
 }
 
-static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val)
+static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *width)
 {
        struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       int stat, bleftend, cleft;
+
+       stat = pvr2_hdw_check_cropcap(cptr->hdw);
        if (stat != 0) {
                return stat;
        }
-       *val = 0;
-       if (cap->bounds.width > cptr->hdw->cropl_val) {
-               *val = cap->bounds.width - cptr->hdw->cropl_val;
-       }
+       bleftend=cap->bounds.left+cap->bounds.width;
+       cleft=cptr->hdw->cropl_val;
+
+       *width= cleft<bleftend ? bleftend-cleft : 0;
        return 0;
 }
 
-static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val)
+static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *height)
 {
        struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       int stat, btopend, ctop;
+
+       stat = pvr2_hdw_check_cropcap(cptr->hdw);
        if (stat != 0) {
                return stat;
        }
-       *val = 0;
-       if (cap->bounds.height > cptr->hdw->cropt_val) {
-               *val = cap->bounds.height - cptr->hdw->cropt_val;
-       }
+       btopend=cap->bounds.top+cap->bounds.height;
+       ctop=cptr->hdw->cropt_val;
+       
+       *height= ctop<btopend ? btopend-ctop : 0;
        return 0;
 }
 
--- linux-2.6.29.6/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2-d.c 
2009-07-03 01:41:20.000000000 +0200
+++ linux-2.6.29.6/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c   
2009-09-05 06:25:43.000000000 +0200
@@ -237,19 +237,33 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l
 static void set_crop(struct pvr2_hdw *hdw)
 {
        struct v4l2_crop crop;
+       struct v4l2_rect *c=&crop.c;
+       int err;
 
        memset(&crop, 0, sizeof crop);
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       crop.c.left = hdw->cropl_val;
-       crop.c.top = hdw->cropt_val;
-       crop.c.height = hdw->croph_val;
-       crop.c.width = hdw->cropw_val;
+       c->left = hdw->cropl_val;
+       c->top = hdw->cropt_val;
+       c->height = hdw->croph_val;
+       c->width = hdw->cropw_val;
 
        pvr2_trace(PVR2_TRACE_CHIPS,
-                  "i2c v4l2 set_crop crop=%d:%d:%d:%d",
-                  crop.c.width, crop.c.height, crop.c.left, crop.c.top);
+                  "i2c v4l2 set_crop S crop=%d:%d:%d:%d",
+                  c->width, c->height, c->left, c->top);
 
-       pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
+       err=pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
+       if(!err) {
+         err=pvr2_i2c_core_cmd(hdw, VIDIOC_G_CROP, &crop);
+         pvr2_trace(PVR2_TRACE_CHIPS,
+                    "i2c v4l2 set_crop G err=%i %d:%d:%d:%d", err, 
+                    c->width, c->height, c->left, c->top);
+         if(!err) {
+           hdw->cropl_val = c->left;
+           hdw->cropt_val = c->top;
+           hdw->croph_val = c->height;
+           hdw->cropw_val = c->width;
+         }
+       }
 }
 
 static int check_crop(struct pvr2_hdw *hdw)
@@ -295,16 +309,23 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2
 
 void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp)
 {
-       int stat;
        struct pvr2_hdw *hdw = cp->hdw;
-       if (hdw->cropcap_stale) {
-               hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP,
-                                          &hdw->cropcap_info);
+       int *ccstale=&hdw->cropcap_stale;
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c pvr2_v4l2_cmd_status_poll cropcap %d",
+                  *ccstale);
+
+       if (*ccstale) {
+               struct v4l2_cropcap *ccinfo=&hdw->cropcap_info;
+               int stat;
+
+               memset(ccinfo, 0, sizeof(*ccinfo));
+               ccinfo->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, ccinfo);
                if (stat == 0) {
                        /* Check was successful, so the data is no
                           longer considered stale. */
-                       hdw->cropcap_stale = 0;
+                       *ccstale = 0;
                }
        }
        pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info);
--- linux-2.6.29.6/drivers/media/video/pvrusb2/pvrusb2-i2c-core-d.c     
2009-07-03 01:41:20.000000000 +0200
+++ linux-2.6.29.6/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c       
2009-09-05 06:01:18.000000000 +0200
@@ -564,7 +564,7 @@ int pvr2_i2c_client_cmd(struct pvr2_i2c_
 int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg)
 {
        struct pvr2_i2c_client *cp, *ncp;
-       int stat = -EINVAL;
+       int stat = -EINVAL, success = 0;
 
        if (!hdw) return stat;
 
@@ -573,10 +573,11 @@ int pvr2_i2c_core_cmd(struct pvr2_hdw *h
                if (!cp->recv_enable) continue;
                mutex_unlock(&hdw->i2c_list_lock);
                stat = pvr2_i2c_client_cmd(cp,cmd,arg);
+               if(!stat) success++;
                mutex_lock(&hdw->i2c_list_lock);
        }
        mutex_unlock(&hdw->i2c_list_lock);
-       return stat;
+       return success ? 0 : stat;
 }
 
 
--- linux-2.6.29.6/include/media/v4l2-subdev-d.h        2009-07-03 
01:41:20.000000000 +0200
+++ linux-2.6.29.6/include/media/v4l2-subdev.h  2009-09-04 03:48:38.000000000 
+0200
@@ -94,6 +94,7 @@ struct v4l2_subdev_tuner_ops {
        int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
        int (*s_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
        int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
+       int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
        int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
        int (*s_config)(struct v4l2_subdev *sd, const struct 
v4l2_priv_tun_config *config);
 };
@@ -113,6 +114,9 @@ struct v4l2_subdev_video_ops {
        int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct 
v4l2_sliced_vbi_cap *cap);
        int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
        int (*s_stream)(struct v4l2_subdev *sd, int enable);
+       int (*cropcap)(struct v4l2_subdev *sd, struct v4l2_cropcap *cap);
+       int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
+       int (*g_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
        int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt);
        int (*g_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt);
 };
_______________________________________________
pvrusb2 mailing list
[email protected]
http://www.isely.net/cgi-bin/mailman/listinfo/pvrusb2

Reply via email to