Fri May 9 23:27:51 CEST 2008 --- linux-2.6.25.1/drivers/media/video/cx25840/cx25840-core-d.c 2008-05-01 23:45:25.000000000 +0200 +++ linux-2.6.25.1/drivers/media/video/cx25840/cx25840-core.c 2008-05-07 22:25:56.000000000 +0200 @@ -704,6 +704,167 @@ static int get_v4lctrl(struct i2c_client /* ----------------------------------------------------------------------- */ +static int origin_v4lcrop(struct i2c_client *client, v4l2_std_id *cstd, int *hbdef, int *vbdef) +{ + v4l2_std_id std = cx25840_get_v4lstd(client); + int hblank, vblank; + + if(std & V4L2_STD_625_50) { + hblank=132; + vblank=36; + } else { + hblank=122; + if(std == V4L2_STD_PAL_M) { + vblank=20; + } else { + vblank=26; + } + } + if(cstd) *cstd=std; + if(hbdef) *hbdef=hblank; + if(vbdef) *vbdef=vblank; + + return 0; +} + +static int v4lcropcap(struct i2c_client *client, struct v4l2_cropcap *cap) +{ + v4l2_std_id std; + int htotal, hbdef, vtotal, vbdef, vactive, doth, dotv; + + if(cap->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + origin_v4lcrop(client, &std, &hbdef, &vbdef); + if(std & V4L2_STD_625_50) { + htotal=864; + vtotal=625; + vactive=580; + doth=59; + dotv=54; + } else { + htotal=858; + vtotal=525; + vactive=487; + doth=10; + dotv=11; + } + + cap->bounds.left=3-hbdef; /* hblank delay >=3 dot */ + cap->bounds.width=htotal-4; /* SAV EAV bt.656 */ + cap->bounds.top=1-vbdef; /* vblank delay >=1 halfline */ + cap->bounds.height=vtotal-3; /* field sync + min_vblank = 2h+1h = 3h */ + + cap->defrect.left=0; + cap->defrect.width=720; + cap->defrect.top=0; + cap->defrect.height=(vactive >> 4) << 4; + + cap->pixelaspect.numerator=dotv; + cap->pixelaspect.denominator=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 set_v4lcrop(struct i2c_client *client, struct v4l2_crop *crop) +{ + v4l2_std_id std; + int is_50Hz; + int hbdef, hbnew, hanew, hsave, hblank, hactive; + int vbdef, vbnew, vbnew656, vanew, vsave, vblank, vblank656, vactive; + + if(crop->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + origin_v4lcrop(client, &std, &hbdef, &vbdef); + + hbnew=crop->c.left+hbdef; + hanew=crop->c.width; + if(hbnew<0 || hbnew>1023 || hanew<0 || hanew>1023) { + v4l_err(client, "invalid horizontal crop %d %d\n", crop->c.left, crop->c.width); + return -ERANGE; + } + + is_50Hz=std & V4L2_STD_625_50; + vbnew=crop->c.top+vbdef; + vbnew656=vbnew+4; + vanew=crop->c.height+(is_50Hz ? 4 : 7); + if(vbnew<0 || vbnew>1023 || vanew<0 || vanew>1023) { + v4l_err(client, "invalid vertical crop %d %d\n", crop->c.top, crop->c.height); + return -ERANGE; + } + + 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 get_v4lcrop(struct i2c_client *client, struct v4l2_crop *crop) +{ + v4l2_std_id std; + int hbdef, hblank, hactive; + int vbdef, vblank, vactive; + + if(crop->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + origin_v4lcrop(client, &std, &hbdef, &vbdef); + + bsa_read(client, 0x470, &hblank, NULL, &hactive); + crop->c.left = hblank-hbdef; + crop->c.width = hactive; + + bsa_read(client, 0x474, &vblank, NULL, &vactive); + crop->c.top = vblank-vbdef; + crop->c.height = vactive - (std & V4L2_STD_625_50 ? 4 : 7); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { switch (fmt->type) { @@ -1066,6 +1227,15 @@ static int cx25840_command(struct i2c_cl case VIDIOC_S_CTRL: return set_v4lctrl(client, (struct v4l2_control *)arg); + case VIDIOC_CROPCAP: + return v4lcropcap(client, (struct v4l2_cropcap *)arg); + + case VIDIOC_G_CROP: + return get_v4lcrop(client, (struct v4l2_crop *)arg); + + case VIDIOC_S_CROP: + return set_v4lcrop(client, (struct v4l2_crop *)arg); + case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; --- linux-2.6.25.1/drivers/media/video/cx25840/cx25840-vbi-d.c 2008-05-01 23:45:25.000000000 +0200 +++ linux-2.6.25.1/drivers/media/video/cx25840/cx25840-vbi.c 2008-05-07 22:28:44.000000000 +0200 @@ -98,12 +98,12 @@ void cx25840_vbi_setup(struct i2c_client } if (std & V4L2_STD_625_50) { - hblank=0x084; - hactive=0x2d0; - burst=0x5d; - vblank=0x024; - vactive=0x244; - vblank656=0x28; + hblank=132; + hactive=720; + burst=93; + vblank=36; + vactive=580; + vblank656=40; src_decimation=0x21f; luma_lpf=2; @@ -140,7 +140,6 @@ void cx25840_vbi_setup(struct i2c_client vblank656=24; burst=0x61; comb=0x20; - sc=555452; } else { vblank=26; @@ -179,9 +178,9 @@ void cx25840_vbi_setup(struct i2c_client "%d.%06d MHz\n", fsc/1000000,fsc%1000000); - 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," + v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i," + " vblank %i, vactive %i, vblank656 %i, src_dec %i," + " burst %i, luma_lpf %i, uv_lpf %i, comb 0x%02x," " sc 0x%06x\n", hblank, hactive, vblank, vactive, vblank656, src_decimation, burst, luma_lpf, uv_lpf, comb, sc);