aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorvdb128@picaros.org <vdb128@picaros.org>2008-08-30 17:26:39 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:36:57 -0400
commite784bfb93c155ba4b354452c69ac02a29d336d97 (patch)
treeda8d1a7ec7803cef22510c505307fd222f05d912 /drivers/media
parentfe15f13679bf52bb5c8acb8b4847e6d73ba62c17 (diff)
V4L/DVB (8896): pvrusb2: Implement crop support
Implement pvrusb2 driver plumbing to support cropping. Submitted by a pvrusb2 user. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h5
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c119
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c7
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c49
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h1
6 files changed, 183 insertions, 2 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 657f861593b..0453244b7fa 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -319,6 +319,7 @@ struct pvr2_hdw {
319 struct pvr2_ctl_info std_info_cur; 319 struct pvr2_ctl_info std_info_cur;
320 struct v4l2_standard *std_defs; 320 struct v4l2_standard *std_defs;
321 const char **std_enum_names; 321 const char **std_enum_names;
322 struct v4l2_cropcap cropcap;
322 323
323 // Generated string names, one per actual V4L2 standard 324 // Generated string names, one per actual V4L2 standard
324 const char *std_mask_ptrs[32]; 325 const char *std_mask_ptrs[32];
@@ -367,6 +368,10 @@ struct pvr2_hdw {
367 VCREATE_DATA(bass); 368 VCREATE_DATA(bass);
368 VCREATE_DATA(treble); 369 VCREATE_DATA(treble);
369 VCREATE_DATA(mute); 370 VCREATE_DATA(mute);
371 VCREATE_DATA(cropl);
372 VCREATE_DATA(cropt);
373 VCREATE_DATA(cropw);
374 VCREATE_DATA(croph);
370 VCREATE_DATA(input); 375 VCREATE_DATA(input);
371 VCREATE_DATA(audiomode); 376 VCREATE_DATA(audiomode);
372 VCREATE_DATA(res_hor); 377 VCREATE_DATA(res_hor);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index a7d636f3f9b..68f4315201a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -402,6 +402,52 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
402 return 0; 402 return 0;
403} 403}
404 404
405static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left)
406{
407 struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
408 if (cap->bounds.width > 0) {
409 /* This statement is present purely to shut up
410 checkpatch.pl */
411 *left = cap->bounds.left - cap->defrect.left;
412 } else {
413 /* This statement is present purely to shut up
414 checkpatch.pl */
415 *left = -119;
416 }
417 return 0;
418}
419
420static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left)
421{
422 struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
423 if (cap->bounds.width > 0) {
424 *left = cap->bounds.left + cap->bounds.width
425 - cap->defrect.left;
426 *left += 3;
427 *left -= cptr->hdw->cropw_val;
428 } else {
429 /* This statement is present purely to shut up
430 checkpatch.pl */
431 *left = 340;
432 }
433 return 0;
434}
435
436static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top)
437{
438 struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
439 if (cap->bounds.height > 0) {
440 /* This statement is present purely to shut up
441 checkpatch.pl */
442 *top = cap->bounds.top - cap->defrect.top;
443 } else {
444 /* This statement is present purely to shut up
445 checkpatch.pl */
446 *top = -19;
447 }
448 return 0;
449}
450
405static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) 451static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
406{ 452{
407 /* Actual maximum depends on the video standard in effect. */ 453 /* Actual maximum depends on the video standard in effect. */
@@ -413,6 +459,19 @@ static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
413 return 0; 459 return 0;
414} 460}
415 461
462static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top)
463{
464 struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
465 if (cap->bounds.height > 0) {
466 *top = cap->bounds.top + cap->bounds.height - cap->defrect.top;
467 *top -= cptr->hdw->croph_val;
468 } else {
469 ctrl_vres_max_get(cptr, top);
470 *top -= 32;
471 }
472 return 0;
473}
474
416static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp) 475static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
417{ 476{
418 /* Actual minimum depends on device digitizer type. */ 477 /* Actual minimum depends on device digitizer type. */
@@ -779,6 +838,10 @@ VCREATE_FUNCS(balance)
779VCREATE_FUNCS(bass) 838VCREATE_FUNCS(bass)
780VCREATE_FUNCS(treble) 839VCREATE_FUNCS(treble)
781VCREATE_FUNCS(mute) 840VCREATE_FUNCS(mute)
841VCREATE_FUNCS(cropl)
842VCREATE_FUNCS(cropt)
843VCREATE_FUNCS(cropw)
844VCREATE_FUNCS(croph)
782VCREATE_FUNCS(audiomode) 845VCREATE_FUNCS(audiomode)
783VCREATE_FUNCS(res_hor) 846VCREATE_FUNCS(res_hor)
784VCREATE_FUNCS(res_ver) 847VCREATE_FUNCS(res_ver)
@@ -849,6 +912,39 @@ static const struct pvr2_ctl_info control_defs[] = {
849 .default_value = 0, 912 .default_value = 0,
850 DEFREF(mute), 913 DEFREF(mute),
851 DEFBOOL, 914 DEFBOOL,
915 }, {
916 .desc = "Capture left margin",
917 .name = "crop_left",
918 .internal_id = PVR2_CID_CROPL,
919 .default_value = 0,
920 DEFREF(cropl),
921 DEFINT(-129, 340),
922 .get_min_value = ctrl_cropl_min_get,
923 .get_max_value = ctrl_cropl_max_get,
924 }, {
925 .desc = "Capture top margin",
926 .name = "crop_top",
927 .internal_id = PVR2_CID_CROPT,
928 .default_value = 0,
929 DEFREF(cropt),
930 DEFINT(-35, 544),
931 .get_min_value = ctrl_cropt_min_get,
932 .get_max_value = ctrl_cropt_max_get,
933 }, {
934 .desc = "Capture width",
935 .name = "crop_width",
936 .internal_id = PVR2_CID_CROPW,
937 .default_value = 720,
938 DEFREF(cropw),
939 DEFINT(388, 849), /* determined empirically, any res_hor>=64 */
940 }, {
941 .desc = "Capture height",
942 .name = "crop_height",
943 .internal_id = PVR2_CID_CROPH,
944 .default_value = 480,
945 DEFREF(croph),
946 DEFINT(32, 576),
947 .get_max_value = ctrl_vres_max_get,
852 },{ 948 },{
853 .desc = "Video Source", 949 .desc = "Video Source",
854 .name = "input", 950 .name = "input",
@@ -2092,6 +2188,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
2092 valid_std_mask; 2188 valid_std_mask;
2093 } 2189 }
2094 2190
2191 memset(&hdw->cropcap, 0, sizeof hdw->cropcap);
2095 hdw->eeprom_addr = -1; 2192 hdw->eeprom_addr = -1;
2096 hdw->unit_number = -1; 2193 hdw->unit_number = -1;
2097 hdw->v4l_minor_number_video = -1; 2194 hdw->v4l_minor_number_video = -1;
@@ -2528,6 +2625,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
2528 /* Can't commit anything until pathway is ok. */ 2625 /* Can't commit anything until pathway is ok. */
2529 return 0; 2626 return 0;
2530 } 2627 }
2628 /* The broadcast decoder can only scale down, so if
2629 * res_*_dirty && crop window < output format ==> enlarge crop.
2630 *
2631 * The mpeg encoder receives fields of res_hor_val dots and
2632 * res_ver_val halflines. Limits: hor<=720, ver<=576.
2633 */
2634 if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
2635 hdw->cropw_val = hdw->res_hor_val;
2636 hdw->cropw_dirty = !0;
2637 } else if (hdw->cropw_dirty) {
2638 hdw->res_hor_dirty = !0; /* must rescale */
2639 hdw->res_hor_val = min(720, hdw->cropw_val);
2640 }
2641 if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
2642 hdw->croph_val = hdw->res_ver_val;
2643 hdw->croph_dirty = !0;
2644 } else if (hdw->croph_dirty) {
2645 int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
2646 hdw->res_ver_dirty = !0;
2647 hdw->res_ver_val = min(nvres, hdw->croph_val);
2648 }
2649
2531 /* If any of the below has changed, then we can't do the update 2650 /* If any of the below has changed, then we can't do the update
2532 while the pipeline is running. Pipeline must be paused first 2651 while the pipeline is running. Pipeline must be paused first
2533 and decoder -> encoder connection be made quiescent before we 2652 and decoder -> encoder connection be made quiescent before we
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index c04956d304a..b4dcda8af64 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -36,6 +36,10 @@
36#define PVR2_CID_FREQUENCY 6 36#define PVR2_CID_FREQUENCY 6
37#define PVR2_CID_HRES 7 37#define PVR2_CID_HRES 7
38#define PVR2_CID_VRES 8 38#define PVR2_CID_VRES 8
39#define PVR2_CID_CROPL 9
40#define PVR2_CID_CROPT 10
41#define PVR2_CID_CROPW 11
42#define PVR2_CID_CROPH 12
39 43
40/* Legal values for the INPUT state variable */ 44/* Legal values for the INPUT state variable */
41#define PVR2_CVAL_INPUT_TV 0 45#define PVR2_CVAL_INPUT_TV 0
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index ccdb429fc7a..94a47718e88 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -37,8 +37,9 @@
37#define OP_VOLUME 3 37#define OP_VOLUME 3
38#define OP_FREQ 4 38#define OP_FREQ 4
39#define OP_AUDIORATE 5 39#define OP_AUDIORATE 5
40#define OP_SIZE 6 40#define OP_CROP 6
41#define OP_LOG 7 41#define OP_SIZE 7
42#define OP_LOG 8
42 43
43static const struct pvr2_i2c_op * const ops[] = { 44static const struct pvr2_i2c_op * const ops[] = {
44 [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, 45 [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
@@ -46,6 +47,7 @@ static const struct pvr2_i2c_op * const ops[] = {
46 [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, 47 [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
47 [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, 48 [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
48 [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, 49 [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
50 [OP_CROP] = &pvr2_i2c_op_v4l2_crop,
49 [OP_SIZE] = &pvr2_i2c_op_v4l2_size, 51 [OP_SIZE] = &pvr2_i2c_op_v4l2_size,
50 [OP_LOG] = &pvr2_i2c_op_v4l2_log, 52 [OP_LOG] = &pvr2_i2c_op_v4l2_log,
51}; 53};
@@ -59,6 +61,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
59 (1 << OP_BCSH) | 61 (1 << OP_BCSH) |
60 (1 << OP_VOLUME) | 62 (1 << OP_VOLUME) |
61 (1 << OP_FREQ) | 63 (1 << OP_FREQ) |
64 (1 << OP_CROP) |
62 (1 << OP_SIZE) | 65 (1 << OP_SIZE) |
63 (1 << OP_LOG)); 66 (1 << OP_LOG));
64 cp->status_poll = pvr2_v4l2_cmd_status_poll; 67 cp->status_poll = pvr2_v4l2_cmd_status_poll;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index 55f04a0b204..440857902c9 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -233,6 +233,55 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
233}; 233};
234 234
235 235
236static void set_crop(struct pvr2_hdw *hdw)
237{
238 struct v4l2_cropcap cap;
239 struct v4l2_crop crop;
240 int stat;
241
242 memset(&cap, 0, sizeof cap);
243 cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
244 stat = pvr2_i2c_core_cmd(hdw, VIDIOC_CROPCAP, &cap);
245 hdw->cropcap = cap;
246
247 memset(&crop, 0, sizeof crop);
248 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
249 crop.c = cap.defrect;
250 crop.c.left += hdw->cropl_val;
251 crop.c.top += hdw->cropt_val;
252 crop.c.height = hdw->croph_val;
253 crop.c.width = hdw->cropw_val;
254
255 pvr2_trace(PVR2_TRACE_CHIPS,
256 "i2c v4l2 set_crop stat=%d cap=%d:%d:%d:%d"
257 " crop=%d:%d:%d:%d", stat, cap.bounds.width,
258 cap.bounds.height, cap.bounds.left, cap.bounds.top,
259 crop.c.width, crop.c.height, crop.c.left, crop.c.top);
260
261 if (stat >= 0) {
262 /* This comment is present purely to keep
263 checkpatch.pl quiet */
264 pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
265 }
266}
267
268static int check_crop(struct pvr2_hdw *hdw)
269{
270 /* The "0 +" stupidity is present only to get checkpatch.pl to
271 shut up. I _want_ those parantheses present so that the
272 two lines automatically line up in my editor. I despise
273 checkpatch.pl. */
274 return 0 + (hdw->cropl_dirty || hdw->cropt_dirty ||
275 hdw->cropw_dirty || hdw->croph_dirty);
276}
277
278const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = {
279 .check = check_crop,
280 .update = set_crop,
281 .name = "v4l2_crop",
282};
283
284
236static void do_log(struct pvr2_hdw *hdw) 285static void do_log(struct pvr2_hdw *hdw)
237{ 286{
238 pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); 287 pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
index 7fa38683b3b..eb744a20610 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
@@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
29extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; 29extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
30extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; 30extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
31extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; 31extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
32extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop;
32extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; 33extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
33extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; 34extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
34extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; 35extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;