summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Isely <isely@pobox.com>2008-08-30 16:26:39 -0500
committerMike Isely <isely@pobox.com>2008-08-30 16:26:39 -0500
commitd060d9f50c2929e5c5a0397843d05d0a27515b70 (patch)
treea59d13ddecc91dce847d18818c8af1842a834ae4
parent3757649a964c5c9a327c83911dcc7743636d5e13 (diff)
downloadmediapointer-dvb-s2-d060d9f50c2929e5c5a0397843d05d0a27515b70.tar.gz
mediapointer-dvb-s2-d060d9f50c2929e5c5a0397843d05d0a27515b70.tar.bz2
pvrusb2: Implement crop support
From: vdb128@picaros.org <vdb128@picaros.org> Implement pvrusb2 driver plumbing to support cropping. Submitted by a pvrusb2 user. Priority: normal Signed-off-by: Mike Isely <isely@pobox.com>
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h5
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c119
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h4
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c7
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c49
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h1
6 files changed, 183 insertions, 2 deletions
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 657f86159..0453244b7 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -319,6 +319,7 @@ struct pvr2_hdw {
struct pvr2_ctl_info std_info_cur;
struct v4l2_standard *std_defs;
const char **std_enum_names;
+ struct v4l2_cropcap cropcap;
// Generated string names, one per actual V4L2 standard
const char *std_mask_ptrs[32];
@@ -367,6 +368,10 @@ struct pvr2_hdw {
VCREATE_DATA(bass);
VCREATE_DATA(treble);
VCREATE_DATA(mute);
+ VCREATE_DATA(cropl);
+ VCREATE_DATA(cropt);
+ VCREATE_DATA(cropw);
+ VCREATE_DATA(croph);
VCREATE_DATA(input);
VCREATE_DATA(audiomode);
VCREATE_DATA(res_hor);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 0fc02ce96..6513139ee 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -403,6 +403,52 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
return 0;
}
+static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
+ if (cap->bounds.width > 0) {
+ /* This statement is present purely to shut up
+ checkpatch.pl */
+ *left = cap->bounds.left - cap->defrect.left;
+ } else {
+ /* This statement is present purely to shut up
+ checkpatch.pl */
+ *left = -119;
+ }
+ return 0;
+}
+
+static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
+ if (cap->bounds.width > 0) {
+ *left = cap->bounds.left + cap->bounds.width
+ - cap->defrect.left;
+ *left += 3;
+ *left -= cptr->hdw->cropw_val;
+ } else {
+ /* This statement is present purely to shut up
+ checkpatch.pl */
+ *left = 340;
+ }
+ return 0;
+}
+
+static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
+ if (cap->bounds.height > 0) {
+ /* This statement is present purely to shut up
+ checkpatch.pl */
+ *top = cap->bounds.top - cap->defrect.top;
+ } else {
+ /* This statement is present purely to shut up
+ checkpatch.pl */
+ *top = -19;
+ }
+ return 0;
+}
+
static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
{
/* Actual maximum depends on the video standard in effect. */
@@ -414,6 +460,19 @@ static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
return 0;
}
+static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
+ if (cap->bounds.height > 0) {
+ *top = cap->bounds.top + cap->bounds.height - cap->defrect.top;
+ *top -= cptr->hdw->croph_val;
+ } else {
+ ctrl_vres_max_get(cptr, top);
+ *top -= 32;
+ }
+ return 0;
+}
+
static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
{
/* Actual minimum depends on device digitizer type. */
@@ -780,6 +839,10 @@ VCREATE_FUNCS(balance)
VCREATE_FUNCS(bass)
VCREATE_FUNCS(treble)
VCREATE_FUNCS(mute)
+VCREATE_FUNCS(cropl)
+VCREATE_FUNCS(cropt)
+VCREATE_FUNCS(cropw)
+VCREATE_FUNCS(croph)
VCREATE_FUNCS(audiomode)
VCREATE_FUNCS(res_hor)
VCREATE_FUNCS(res_ver)
@@ -850,6 +913,39 @@ static const struct pvr2_ctl_info control_defs[] = {
.default_value = 0,
DEFREF(mute),
DEFBOOL,
+ }, {
+ .desc = "Capture left margin",
+ .name = "crop_left",
+ .internal_id = PVR2_CID_CROPL,
+ .default_value = 0,
+ DEFREF(cropl),
+ DEFINT(-129, 340),
+ .get_min_value = ctrl_cropl_min_get,
+ .get_max_value = ctrl_cropl_max_get,
+ }, {
+ .desc = "Capture top margin",
+ .name = "crop_top",
+ .internal_id = PVR2_CID_CROPT,
+ .default_value = 0,
+ DEFREF(cropt),
+ DEFINT(-35, 544),
+ .get_min_value = ctrl_cropt_min_get,
+ .get_max_value = ctrl_cropt_max_get,
+ }, {
+ .desc = "Capture width",
+ .name = "crop_width",
+ .internal_id = PVR2_CID_CROPW,
+ .default_value = 720,
+ DEFREF(cropw),
+ DEFINT(388, 849), /* determined empirically, any res_hor>=64 */
+ }, {
+ .desc = "Capture height",
+ .name = "crop_height",
+ .internal_id = PVR2_CID_CROPH,
+ .default_value = 480,
+ DEFREF(croph),
+ DEFINT(32, 576),
+ .get_max_value = ctrl_vres_max_get,
},{
.desc = "Video Source",
.name = "input",
@@ -2109,6 +2205,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
valid_std_mask;
}
+ memset(&hdw->cropcap, 0, sizeof hdw->cropcap);
hdw->eeprom_addr = -1;
hdw->unit_number = -1;
hdw->v4l_minor_number_video = -1;
@@ -2552,6 +2649,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
/* Can't commit anything until pathway is ok. */
return 0;
}
+ /* The broadcast decoder can only scale down, so if
+ * res_*_dirty && crop window < output format ==> enlarge crop.
+ *
+ * The mpeg encoder receives fields of res_hor_val dots and
+ * res_ver_val halflines. Limits: hor<=720, ver<=576.
+ */
+ if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
+ hdw->cropw_val = hdw->res_hor_val;
+ hdw->cropw_dirty = !0;
+ } else if (hdw->cropw_dirty) {
+ hdw->res_hor_dirty = !0; /* must rescale */
+ hdw->res_hor_val = min(720, hdw->cropw_val);
+ }
+ if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
+ hdw->croph_val = hdw->res_ver_val;
+ hdw->croph_dirty = !0;
+ } else if (hdw->croph_dirty) {
+ int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
+ hdw->res_ver_dirty = !0;
+ hdw->res_ver_val = min(nvres, hdw->croph_val);
+ }
+
/* If any of the below has changed, then we can't do the update
while the pipeline is running. Pipeline must be paused first
and decoder -> encoder connection be made quiescent before we
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 4e60f6262..0c3ae2586 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -37,6 +37,10 @@
#define PVR2_CID_FREQUENCY 6
#define PVR2_CID_HRES 7
#define PVR2_CID_VRES 8
+#define PVR2_CID_CROPL 9
+#define PVR2_CID_CROPT 10
+#define PVR2_CID_CROPW 11
+#define PVR2_CID_CROPH 12
/* Legal values for the INPUT state variable */
#define PVR2_CVAL_INPUT_TV 0
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index 25e611b2e..1b1424955 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -38,8 +38,9 @@
#define OP_VOLUME 3
#define OP_FREQ 4
#define OP_AUDIORATE 5
-#define OP_SIZE 6
-#define OP_LOG 7
+#define OP_CROP 6
+#define OP_SIZE 7
+#define OP_LOG 8
static const struct pvr2_i2c_op * const ops[] = {
[OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
@@ -47,6 +48,7 @@ static const struct pvr2_i2c_op * const ops[] = {
[OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
[OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
[OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
+ [OP_CROP] = &pvr2_i2c_op_v4l2_crop,
[OP_SIZE] = &pvr2_i2c_op_v4l2_size,
[OP_LOG] = &pvr2_i2c_op_v4l2_log,
};
@@ -60,6 +62,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
(1 << OP_BCSH) |
(1 << OP_VOLUME) |
(1 << OP_FREQ) |
+ (1 << OP_CROP) |
(1 << OP_SIZE) |
(1 << OP_LOG));
cp->status_poll = pvr2_v4l2_cmd_status_poll;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index d715c80ef..602bc5309 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -234,6 +234,55 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
};
+static void set_crop(struct pvr2_hdw *hdw)
+{
+ struct v4l2_cropcap cap;
+ struct v4l2_crop crop;
+ int stat;
+
+ memset(&cap, 0, sizeof cap);
+ cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ stat = pvr2_i2c_core_cmd(hdw, VIDIOC_CROPCAP, &cap);
+ hdw->cropcap = cap;
+
+ memset(&crop, 0, sizeof crop);
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c = cap.defrect;
+ crop.c.left += hdw->cropl_val;
+ crop.c.top += hdw->cropt_val;
+ crop.c.height = hdw->croph_val;
+ crop.c.width = hdw->cropw_val;
+
+ pvr2_trace(PVR2_TRACE_CHIPS,
+ "i2c v4l2 set_crop stat=%d cap=%d:%d:%d:%d"
+ " crop=%d:%d:%d:%d", stat, cap.bounds.width,
+ cap.bounds.height, cap.bounds.left, cap.bounds.top,
+ crop.c.width, crop.c.height, crop.c.left, crop.c.top);
+
+ if (stat >= 0) {
+ /* This comment is present purely to keep
+ checkpatch.pl quiet */
+ pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
+ }
+}
+
+static int check_crop(struct pvr2_hdw *hdw)
+{
+ /* The "0 +" stupidity is present only to get checkpatch.pl to
+ shut up. I _want_ those parantheses present so that the
+ two lines automatically line up in my editor. I despise
+ checkpatch.pl. */
+ return 0 + (hdw->cropl_dirty || hdw->cropt_dirty ||
+ hdw->cropw_dirty || hdw->croph_dirty);
+}
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = {
+ .check = check_crop,
+ .update = set_crop,
+ .name = "v4l2_crop",
+};
+
+
static void do_log(struct pvr2_hdw *hdw)
{
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
index 7fa38683b..eb744a206 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
@@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;