diff options
author | vdb128@picaros.org <vdb128@picaros.org> | 2008-08-30 17:26:39 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 07:36:57 -0400 |
commit | e784bfb93c155ba4b354452c69ac02a29d336d97 (patch) | |
tree | da8d1a7ec7803cef22510c505307fd222f05d912 /drivers/media/video/pvrusb2 | |
parent | fe15f13679bf52bb5c8acb8b4847e6d73ba62c17 (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/video/pvrusb2')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 5 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 119 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.h | 4 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 7 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 49 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 1 |
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 657f861593b3..0453244b7fa2 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 a7d636f3f9b6..68f4315201a5 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 | ||
405 | static 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 | |||
420 | static 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 | |||
436 | static 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 | |||
405 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | 451 | static 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 | ||
462 | static 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 | |||
416 | static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp) | 475 | static 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) | |||
779 | VCREATE_FUNCS(bass) | 838 | VCREATE_FUNCS(bass) |
780 | VCREATE_FUNCS(treble) | 839 | VCREATE_FUNCS(treble) |
781 | VCREATE_FUNCS(mute) | 840 | VCREATE_FUNCS(mute) |
841 | VCREATE_FUNCS(cropl) | ||
842 | VCREATE_FUNCS(cropt) | ||
843 | VCREATE_FUNCS(cropw) | ||
844 | VCREATE_FUNCS(croph) | ||
782 | VCREATE_FUNCS(audiomode) | 845 | VCREATE_FUNCS(audiomode) |
783 | VCREATE_FUNCS(res_hor) | 846 | VCREATE_FUNCS(res_hor) |
784 | VCREATE_FUNCS(res_ver) | 847 | VCREATE_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 c04956d304a7..b4dcda8af64a 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 ccdb429fc7af..94a47718e88e 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 | ||
43 | static const struct pvr2_i2c_op * const ops[] = { | 44 | static 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 55f04a0b2047..440857902c92 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 | ||
236 | static 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 | |||
268 | static 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 | |||
278 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { | ||
279 | .check = check_crop, | ||
280 | .update = set_crop, | ||
281 | .name = "v4l2_crop", | ||
282 | }; | ||
283 | |||
284 | |||
236 | static void do_log(struct pvr2_hdw *hdw) | 285 | static 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 7fa38683b3b1..eb744a20610d 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; | |||
29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; | 29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; |
30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; | 30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; |
31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; | 31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; |
32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop; | ||
32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; | 33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; |
33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; | 34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; |
34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; | 35 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; |