diff options
author | Mike Isely <isely@pobox.com> | 2008-08-31 20:02:20 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 07:36:57 -0400 |
commit | 432907f750b27aa2b41e1bf398e6eb711ead448f (patch) | |
tree | 6738e7e4650b216724971587efa90581ba4c85aa /drivers/media/video/pvrusb2 | |
parent | 0b7c2c9598e7447ad6a9d157491e6c5459ae56de (diff) |
V4L/DVB (8900): pvrusb2: Implement cropping pass through
This builds upon the previous pvrusb2 change to more formally
implement full cropping support. This enables access from the
driver's V4L interface, and enables access to full capabilities from
sysfs as well. Note that this is only effective when in analog mode.
It also will only work when the underlying digitizer's driver (saa7115
or cx25840 depending on the hardware) also implements the appropriate
functions.
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 | 311 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.h | 9 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 37 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 2 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 86 |
6 files changed, 383 insertions, 67 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 8bc9669733df..de7ee7264be6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -308,6 +308,10 @@ struct pvr2_hdw { | |||
308 | struct v4l2_tuner tuner_signal_info; | 308 | struct v4l2_tuner tuner_signal_info; |
309 | int tuner_signal_stale; | 309 | int tuner_signal_stale; |
310 | 310 | ||
311 | /* Cropping capability info */ | ||
312 | struct v4l2_cropcap cropcap_info; | ||
313 | int cropcap_stale; | ||
314 | |||
311 | /* Video standard handling */ | 315 | /* Video standard handling */ |
312 | v4l2_std_id std_mask_eeprom; // Hardware supported selections | 316 | v4l2_std_id std_mask_eeprom; // Hardware supported selections |
313 | v4l2_std_id std_mask_avail; // Which standards we may select from | 317 | v4l2_std_id std_mask_avail; // Which standards we may select from |
@@ -320,7 +324,6 @@ struct pvr2_hdw { | |||
320 | struct pvr2_ctl_info std_info_cur; | 324 | struct pvr2_ctl_info std_info_cur; |
321 | struct v4l2_standard *std_defs; | 325 | struct v4l2_standard *std_defs; |
322 | const char **std_enum_names; | 326 | const char **std_enum_names; |
323 | struct v4l2_cropcap cropcap; | ||
324 | 327 | ||
325 | // Generated string names, one per actual V4L2 standard | 328 | // Generated string names, one per actual V4L2 standard |
326 | const char *std_mask_ptrs[32]; | 329 | const char *std_mask_ptrs[32]; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e29a39ffdcca..9bb59b2de917 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -298,6 +298,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, | |||
298 | unsigned int timeout,int probe_fl, | 298 | unsigned int timeout,int probe_fl, |
299 | void *write_data,unsigned int write_len, | 299 | void *write_data,unsigned int write_len, |
300 | void *read_data,unsigned int read_len); | 300 | void *read_data,unsigned int read_len); |
301 | static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw); | ||
301 | 302 | ||
302 | 303 | ||
303 | static void trace_stbit(const char *name,int val) | 304 | static void trace_stbit(const char *name,int val) |
@@ -404,70 +405,220 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) | |||
404 | 405 | ||
405 | static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) | 406 | static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) |
406 | { | 407 | { |
407 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap; | 408 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; |
408 | if (cap->bounds.width > 0) { | 409 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); |
409 | /* This statement is present purely to shut up | 410 | if (stat != 0) { |
410 | checkpatch.pl */ | 411 | /* Keep checkpatch.pl quiet */ |
411 | *left = cap->bounds.left - cap->defrect.left; | 412 | return stat; |
412 | } else { | ||
413 | /* This statement is present purely to shut up | ||
414 | checkpatch.pl */ | ||
415 | *left = -119; | ||
416 | } | 413 | } |
414 | *left = cap->bounds.left; | ||
417 | return 0; | 415 | return 0; |
418 | } | 416 | } |
419 | 417 | ||
420 | static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) | 418 | static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) |
421 | { | 419 | { |
422 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap; | 420 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; |
423 | if (cap->bounds.width > 0) { | 421 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); |
424 | *left = cap->bounds.left + cap->bounds.width | 422 | if (stat != 0) { |
425 | - cap->defrect.left; | 423 | /* Keep checkpatch.pl quiet */ |
426 | *left += 3; | 424 | return stat; |
427 | *left -= cptr->hdw->cropw_val; | 425 | } |
428 | } else { | 426 | *left = cap->bounds.left; |
427 | if (cap->bounds.width > cptr->hdw->cropw_val) { | ||
429 | /* This statement is present purely to shut up | 428 | /* This statement is present purely to shut up |
430 | checkpatch.pl */ | 429 | checkpatch.pl */ |
431 | *left = 340; | 430 | *left += cap->bounds.width - cptr->hdw->cropw_val; |
432 | } | 431 | } |
433 | return 0; | 432 | return 0; |
434 | } | 433 | } |
435 | 434 | ||
436 | static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) | 435 | static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) |
437 | { | 436 | { |
438 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap; | 437 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; |
439 | if (cap->bounds.height > 0) { | 438 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); |
440 | /* This statement is present purely to shut up | 439 | if (stat != 0) { |
441 | checkpatch.pl */ | 440 | /* Keep checkpatch.pl quiet */ |
442 | *top = cap->bounds.top - cap->defrect.top; | 441 | return stat; |
443 | } else { | ||
444 | /* This statement is present purely to shut up | ||
445 | checkpatch.pl */ | ||
446 | *top = -19; | ||
447 | } | 442 | } |
443 | *top = cap->bounds.top; | ||
448 | return 0; | 444 | return 0; |
449 | } | 445 | } |
450 | 446 | ||
451 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | 447 | static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) |
452 | { | 448 | { |
453 | /* Actual maximum depends on the video standard in effect. */ | 449 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; |
454 | if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) { | 450 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); |
455 | *vp = 480; | 451 | if (stat != 0) { |
456 | } else { | 452 | /* Keep checkpatch.pl quiet */ |
457 | *vp = 576; | 453 | return stat; |
454 | } | ||
455 | *top = cap->bounds.top; | ||
456 | if (cap->bounds.height > cptr->hdw->croph_val) { | ||
457 | /* Keep checkpatch.pl quiet */ | ||
458 | *top += cap->bounds.height - cptr->hdw->croph_val; | ||
458 | } | 459 | } |
459 | return 0; | 460 | return 0; |
460 | } | 461 | } |
461 | 462 | ||
462 | static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) | 463 | static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val) |
463 | { | 464 | { |
464 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap; | 465 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; |
465 | if (cap->bounds.height > 0) { | 466 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); |
466 | *top = cap->bounds.top + cap->bounds.height - cap->defrect.top; | 467 | if (stat != 0) { |
467 | *top -= cptr->hdw->croph_val; | 468 | /* Keep checkpatch.pl quiet */ |
469 | return stat; | ||
470 | } | ||
471 | *val = 0; | ||
472 | if (cap->bounds.width > cptr->hdw->cropl_val) { | ||
473 | /* Keep checkpatch.pl quiet */ | ||
474 | *val = cap->bounds.width - cptr->hdw->cropl_val; | ||
475 | } | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val) | ||
480 | { | ||
481 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
482 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
483 | if (stat != 0) { | ||
484 | /* Keep checkpatch.pl quiet */ | ||
485 | return stat; | ||
486 | } | ||
487 | *val = 0; | ||
488 | if (cap->bounds.height > cptr->hdw->cropt_val) { | ||
489 | /* Keep checkpatch.pl quiet */ | ||
490 | *val = cap->bounds.height - cptr->hdw->cropt_val; | ||
491 | } | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val) | ||
496 | { | ||
497 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
498 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
499 | if (stat != 0) { | ||
500 | /* Keep checkpatch.pl quiet */ | ||
501 | return stat; | ||
502 | } | ||
503 | *val = cap->bounds.left; | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val) | ||
508 | { | ||
509 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
510 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
511 | if (stat != 0) { | ||
512 | /* Keep checkpatch.pl quiet */ | ||
513 | return stat; | ||
514 | } | ||
515 | *val = cap->bounds.top; | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val) | ||
520 | { | ||
521 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
522 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
523 | if (stat != 0) { | ||
524 | /* Keep checkpatch.pl quiet */ | ||
525 | return stat; | ||
526 | } | ||
527 | *val = cap->bounds.width; | ||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val) | ||
532 | { | ||
533 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
534 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
535 | if (stat != 0) { | ||
536 | /* Keep checkpatch.pl quiet */ | ||
537 | return stat; | ||
538 | } | ||
539 | *val = cap->bounds.height; | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val) | ||
544 | { | ||
545 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
546 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
547 | if (stat != 0) { | ||
548 | /* Keep checkpatch.pl quiet */ | ||
549 | return stat; | ||
550 | } | ||
551 | *val = cap->defrect.left; | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val) | ||
556 | { | ||
557 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
558 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
559 | if (stat != 0) { | ||
560 | /* Keep checkpatch.pl quiet */ | ||
561 | return stat; | ||
562 | } | ||
563 | *val = cap->defrect.top; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val) | ||
568 | { | ||
569 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
570 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
571 | if (stat != 0) { | ||
572 | /* Keep checkpatch.pl quiet */ | ||
573 | return stat; | ||
574 | } | ||
575 | *val = cap->defrect.width; | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val) | ||
580 | { | ||
581 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
582 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
583 | if (stat != 0) { | ||
584 | /* Keep checkpatch.pl quiet */ | ||
585 | return stat; | ||
586 | } | ||
587 | *val = cap->defrect.height; | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val) | ||
592 | { | ||
593 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
594 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
595 | if (stat != 0) { | ||
596 | /* Keep checkpatch.pl quiet */ | ||
597 | return stat; | ||
598 | } | ||
599 | *val = cap->pixelaspect.numerator; | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val) | ||
604 | { | ||
605 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
606 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
607 | if (stat != 0) { | ||
608 | /* Keep checkpatch.pl quiet */ | ||
609 | return stat; | ||
610 | } | ||
611 | *val = cap->pixelaspect.denominator; | ||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | ||
616 | { | ||
617 | /* Actual maximum depends on the video standard in effect. */ | ||
618 | if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) { | ||
619 | *vp = 480; | ||
468 | } else { | 620 | } else { |
469 | ctrl_vres_max_get(cptr, top); | 621 | *vp = 576; |
470 | *top -= 32; | ||
471 | } | 622 | } |
472 | return 0; | 623 | return 0; |
473 | } | 624 | } |
@@ -913,7 +1064,7 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
913 | DEFREF(mute), | 1064 | DEFREF(mute), |
914 | DEFBOOL, | 1065 | DEFBOOL, |
915 | }, { | 1066 | }, { |
916 | .desc = "Capture left margin", | 1067 | .desc = "Capture crop left margin", |
917 | .name = "crop_left", | 1068 | .name = "crop_left", |
918 | .internal_id = PVR2_CID_CROPL, | 1069 | .internal_id = PVR2_CID_CROPL, |
919 | .default_value = 0, | 1070 | .default_value = 0, |
@@ -921,8 +1072,9 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
921 | DEFINT(-129, 340), | 1072 | DEFINT(-129, 340), |
922 | .get_min_value = ctrl_cropl_min_get, | 1073 | .get_min_value = ctrl_cropl_min_get, |
923 | .get_max_value = ctrl_cropl_max_get, | 1074 | .get_max_value = ctrl_cropl_max_get, |
1075 | .get_def_value = ctrl_get_cropcapdl, | ||
924 | }, { | 1076 | }, { |
925 | .desc = "Capture top margin", | 1077 | .desc = "Capture crop top margin", |
926 | .name = "crop_top", | 1078 | .name = "crop_top", |
927 | .internal_id = PVR2_CID_CROPT, | 1079 | .internal_id = PVR2_CID_CROPT, |
928 | .default_value = 0, | 1080 | .default_value = 0, |
@@ -930,21 +1082,53 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
930 | DEFINT(-35, 544), | 1082 | DEFINT(-35, 544), |
931 | .get_min_value = ctrl_cropt_min_get, | 1083 | .get_min_value = ctrl_cropt_min_get, |
932 | .get_max_value = ctrl_cropt_max_get, | 1084 | .get_max_value = ctrl_cropt_max_get, |
1085 | .get_def_value = ctrl_get_cropcapdt, | ||
933 | }, { | 1086 | }, { |
934 | .desc = "Capture width", | 1087 | .desc = "Capture crop width", |
935 | .name = "crop_width", | 1088 | .name = "crop_width", |
936 | .internal_id = PVR2_CID_CROPW, | 1089 | .internal_id = PVR2_CID_CROPW, |
937 | .default_value = 720, | 1090 | .default_value = 720, |
938 | DEFREF(cropw), | 1091 | DEFREF(cropw), |
939 | DEFINT(388, 849), /* determined empirically, any res_hor>=64 */ | 1092 | .get_max_value = ctrl_cropw_max_get, |
1093 | .get_def_value = ctrl_get_cropcapdw, | ||
940 | }, { | 1094 | }, { |
941 | .desc = "Capture height", | 1095 | .desc = "Capture crop height", |
942 | .name = "crop_height", | 1096 | .name = "crop_height", |
943 | .internal_id = PVR2_CID_CROPH, | 1097 | .internal_id = PVR2_CID_CROPH, |
944 | .default_value = 480, | 1098 | .default_value = 480, |
945 | DEFREF(croph), | 1099 | DEFREF(croph), |
946 | DEFINT(32, 576), | 1100 | .get_max_value = ctrl_croph_max_get, |
947 | .get_max_value = ctrl_vres_max_get, | 1101 | .get_def_value = ctrl_get_cropcapdh, |
1102 | }, { | ||
1103 | .desc = "Capture capability pixel aspect numerator", | ||
1104 | .name = "cropcap_pixel_numerator", | ||
1105 | .internal_id = PVR2_CID_CROPCAPPAN, | ||
1106 | .get_value = ctrl_get_cropcappan, | ||
1107 | }, { | ||
1108 | .desc = "Capture capability pixel aspect denominator", | ||
1109 | .name = "cropcap_pixel_denominator", | ||
1110 | .internal_id = PVR2_CID_CROPCAPPAD, | ||
1111 | .get_value = ctrl_get_cropcappad, | ||
1112 | }, { | ||
1113 | .desc = "Capture capability bounds top", | ||
1114 | .name = "cropcap_bounds_top", | ||
1115 | .internal_id = PVR2_CID_CROPCAPBT, | ||
1116 | .get_value = ctrl_get_cropcapbt, | ||
1117 | }, { | ||
1118 | .desc = "Capture capability bounds left", | ||
1119 | .name = "cropcap_bounds_left", | ||
1120 | .internal_id = PVR2_CID_CROPCAPBL, | ||
1121 | .get_value = ctrl_get_cropcapbl, | ||
1122 | }, { | ||
1123 | .desc = "Capture capability bounds width", | ||
1124 | .name = "cropcap_bounds_width", | ||
1125 | .internal_id = PVR2_CID_CROPCAPBW, | ||
1126 | .get_value = ctrl_get_cropcapbw, | ||
1127 | }, { | ||
1128 | .desc = "Capture capability bounds height", | ||
1129 | .name = "cropcap_bounds_height", | ||
1130 | .internal_id = PVR2_CID_CROPCAPBH, | ||
1131 | .get_value = ctrl_get_cropcapbh, | ||
948 | },{ | 1132 | },{ |
949 | .desc = "Video Source", | 1133 | .desc = "Video Source", |
950 | .name = "input", | 1134 | .name = "input", |
@@ -2188,7 +2372,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2188 | valid_std_mask; | 2372 | valid_std_mask; |
2189 | } | 2373 | } |
2190 | 2374 | ||
2191 | memset(&hdw->cropcap, 0, sizeof hdw->cropcap); | 2375 | hdw->cropcap_stale = !0; |
2192 | hdw->eeprom_addr = -1; | 2376 | hdw->eeprom_addr = -1; |
2193 | hdw->unit_number = -1; | 2377 | hdw->unit_number = -1; |
2194 | hdw->v4l_minor_number_video = -1; | 2378 | hdw->v4l_minor_number_video = -1; |
@@ -2728,6 +2912,9 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
2728 | } | 2912 | } |
2729 | 2913 | ||
2730 | hdw->state_pipeline_config = !0; | 2914 | hdw->state_pipeline_config = !0; |
2915 | /* Hardware state may have changed in a way to cause the cropping | ||
2916 | capabilities to have changed. So mark it stale, which will | ||
2917 | cause a later re-fetch. */ | ||
2731 | trace_stbit("state_pipeline_config",hdw->state_pipeline_config); | 2918 | trace_stbit("state_pipeline_config",hdw->state_pipeline_config); |
2732 | return !0; | 2919 | return !0; |
2733 | } | 2920 | } |
@@ -2818,6 +3005,36 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) | |||
2818 | } | 3005 | } |
2819 | 3006 | ||
2820 | 3007 | ||
3008 | static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) | ||
3009 | { | ||
3010 | if (!hdw->cropcap_stale) { | ||
3011 | /* Keep checkpatch.pl quiet */ | ||
3012 | return 0; | ||
3013 | } | ||
3014 | pvr2_i2c_core_status_poll(hdw); | ||
3015 | if (hdw->cropcap_stale) { | ||
3016 | /* Keep checkpatch.pl quiet */ | ||
3017 | return -EIO; | ||
3018 | } | ||
3019 | return 0; | ||
3020 | } | ||
3021 | |||
3022 | |||
3023 | /* Return information about cropping capabilities */ | ||
3024 | int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp) | ||
3025 | { | ||
3026 | int stat = 0; | ||
3027 | LOCK_TAKE(hdw->big_lock); | ||
3028 | stat = pvr2_hdw_check_cropcap(hdw); | ||
3029 | if (!stat) { | ||
3030 | /* Keep checkpatch.pl quiet */ | ||
3031 | memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info)); | ||
3032 | } | ||
3033 | LOCK_GIVE(hdw->big_lock); | ||
3034 | return stat; | ||
3035 | } | ||
3036 | |||
3037 | |||
2821 | /* Return information about the tuner */ | 3038 | /* Return information about the tuner */ |
2822 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) | 3039 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) |
2823 | { | 3040 | { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index b4dcda8af64a..49482d1f2b28 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -40,6 +40,12 @@ | |||
40 | #define PVR2_CID_CROPT 10 | 40 | #define PVR2_CID_CROPT 10 |
41 | #define PVR2_CID_CROPW 11 | 41 | #define PVR2_CID_CROPW 11 |
42 | #define PVR2_CID_CROPH 12 | 42 | #define PVR2_CID_CROPH 12 |
43 | #define PVR2_CID_CROPCAPPAN 13 | ||
44 | #define PVR2_CID_CROPCAPPAD 14 | ||
45 | #define PVR2_CID_CROPCAPBL 15 | ||
46 | #define PVR2_CID_CROPCAPBT 16 | ||
47 | #define PVR2_CID_CROPCAPBW 17 | ||
48 | #define PVR2_CID_CROPCAPBH 18 | ||
43 | 49 | ||
44 | /* Legal values for the INPUT state variable */ | 50 | /* Legal values for the INPUT state variable */ |
45 | #define PVR2_CVAL_INPUT_TV 0 | 51 | #define PVR2_CVAL_INPUT_TV 0 |
@@ -174,6 +180,9 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); | |||
174 | /* Return information about the tuner */ | 180 | /* Return information about the tuner */ |
175 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); | 181 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); |
176 | 182 | ||
183 | /* Return information about cropping capabilities */ | ||
184 | int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *); | ||
185 | |||
177 | /* Query device and see if it thinks it is on a high-speed USB link */ | 186 | /* Query device and see if it thinks it is on a high-speed USB link */ |
178 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); | 187 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); |
179 | 188 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 440857902c92..543fa30b777e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | |||
@@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw) | |||
37 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); | 37 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); |
38 | } | 38 | } |
39 | hdw->tuner_signal_stale = !0; | 39 | hdw->tuner_signal_stale = !0; |
40 | hdw->cropcap_stale = !0; | ||
40 | } | 41 | } |
41 | 42 | ||
42 | 43 | ||
@@ -235,34 +236,20 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { | |||
235 | 236 | ||
236 | static void set_crop(struct pvr2_hdw *hdw) | 237 | static void set_crop(struct pvr2_hdw *hdw) |
237 | { | 238 | { |
238 | struct v4l2_cropcap cap; | ||
239 | struct v4l2_crop crop; | 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 | 240 | ||
247 | memset(&crop, 0, sizeof crop); | 241 | memset(&crop, 0, sizeof crop); |
248 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 242 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
249 | crop.c = cap.defrect; | 243 | crop.c.left = hdw->cropl_val; |
250 | crop.c.left += hdw->cropl_val; | 244 | crop.c.top = hdw->cropt_val; |
251 | crop.c.top += hdw->cropt_val; | ||
252 | crop.c.height = hdw->croph_val; | 245 | crop.c.height = hdw->croph_val; |
253 | crop.c.width = hdw->cropw_val; | 246 | crop.c.width = hdw->cropw_val; |
254 | 247 | ||
255 | pvr2_trace(PVR2_TRACE_CHIPS, | 248 | pvr2_trace(PVR2_TRACE_CHIPS, |
256 | "i2c v4l2 set_crop stat=%d cap=%d:%d:%d:%d" | 249 | "i2c v4l2 set_crop crop=%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); | 250 | crop.c.width, crop.c.height, crop.c.left, crop.c.top); |
260 | 251 | ||
261 | if (stat >= 0) { | 252 | pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); |
262 | /* This comment is present purely to keep | ||
263 | checkpatch.pl quiet */ | ||
264 | pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); | ||
265 | } | ||
266 | } | 253 | } |
267 | 254 | ||
268 | static int check_crop(struct pvr2_hdw *hdw) | 255 | static int check_crop(struct pvr2_hdw *hdw) |
@@ -312,7 +299,19 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) | |||
312 | 299 | ||
313 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) | 300 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) |
314 | { | 301 | { |
315 | pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info); | 302 | int stat; |
303 | struct pvr2_hdw *hdw = cp->hdw; | ||
304 | if (hdw->cropcap_stale) { | ||
305 | hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
306 | stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, | ||
307 | &hdw->cropcap_info); | ||
308 | if (stat == 0) { | ||
309 | /* Check was successful, so the data is no | ||
310 | longer considered stale. */ | ||
311 | hdw->cropcap_stale = 0; | ||
312 | } | ||
313 | } | ||
314 | pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info); | ||
316 | } | 315 | } |
317 | 316 | ||
318 | 317 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index e600576a6c4b..afb53b49b31a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -891,6 +891,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) | |||
891 | INIT_LIST_HEAD(&cp->list); | 891 | INIT_LIST_HEAD(&cp->list); |
892 | cp->client = client; | 892 | cp->client = client; |
893 | mutex_lock(&hdw->i2c_list_lock); do { | 893 | mutex_lock(&hdw->i2c_list_lock); do { |
894 | hdw->cropcap_stale = !0; | ||
894 | list_add_tail(&cp->list,&hdw->i2c_clients); | 895 | list_add_tail(&cp->list,&hdw->i2c_clients); |
895 | hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; | 896 | hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; |
896 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | 897 | } while (0); mutex_unlock(&hdw->i2c_list_lock); |
@@ -905,6 +906,7 @@ static int pvr2_i2c_detach_inform(struct i2c_client *client) | |||
905 | unsigned long amask = 0; | 906 | unsigned long amask = 0; |
906 | int foundfl = 0; | 907 | int foundfl = 0; |
907 | mutex_lock(&hdw->i2c_list_lock); do { | 908 | mutex_lock(&hdw->i2c_list_lock); do { |
909 | hdw->cropcap_stale = !0; | ||
908 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { | 910 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { |
909 | if (cp->client == client) { | 911 | if (cp->client == client) { |
910 | trace_i2c("pvr2_i2c_detach" | 912 | trace_i2c("pvr2_i2c_detach" |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index c53037a25570..f048d80b77e5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -755,6 +755,92 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
755 | break; | 755 | break; |
756 | } | 756 | } |
757 | 757 | ||
758 | case VIDIOC_CROPCAP: | ||
759 | { | ||
760 | struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg; | ||
761 | if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
762 | ret = -EINVAL; | ||
763 | break; | ||
764 | } | ||
765 | ret = pvr2_hdw_get_cropcap(hdw, cap); | ||
766 | cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */ | ||
767 | break; | ||
768 | } | ||
769 | case VIDIOC_G_CROP: | ||
770 | { | ||
771 | struct v4l2_crop *crop = (struct v4l2_crop *)arg; | ||
772 | int val = 0; | ||
773 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
774 | ret = -EINVAL; | ||
775 | break; | ||
776 | } | ||
777 | ret = pvr2_ctrl_get_value( | ||
778 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); | ||
779 | if (ret != 0) { | ||
780 | ret = -EINVAL; | ||
781 | break; | ||
782 | } | ||
783 | crop->c.left = val; | ||
784 | ret = pvr2_ctrl_get_value( | ||
785 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); | ||
786 | if (ret != 0) { | ||
787 | ret = -EINVAL; | ||
788 | break; | ||
789 | } | ||
790 | crop->c.top = val; | ||
791 | ret = pvr2_ctrl_get_value( | ||
792 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); | ||
793 | if (ret != 0) { | ||
794 | ret = -EINVAL; | ||
795 | break; | ||
796 | } | ||
797 | crop->c.width = val; | ||
798 | ret = pvr2_ctrl_get_value( | ||
799 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); | ||
800 | if (ret != 0) { | ||
801 | ret = -EINVAL; | ||
802 | break; | ||
803 | } | ||
804 | crop->c.height = val; | ||
805 | } | ||
806 | case VIDIOC_S_CROP: | ||
807 | { | ||
808 | struct v4l2_crop *crop = (struct v4l2_crop *)arg; | ||
809 | struct v4l2_cropcap cap; | ||
810 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
811 | ret = -EINVAL; | ||
812 | break; | ||
813 | } | ||
814 | cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
815 | ret = pvr2_ctrl_set_value( | ||
816 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), | ||
817 | crop->c.left); | ||
818 | if (ret != 0) { | ||
819 | ret = -EINVAL; | ||
820 | break; | ||
821 | } | ||
822 | ret = pvr2_ctrl_set_value( | ||
823 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), | ||
824 | crop->c.top); | ||
825 | if (ret != 0) { | ||
826 | ret = -EINVAL; | ||
827 | break; | ||
828 | } | ||
829 | ret = pvr2_ctrl_set_value( | ||
830 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), | ||
831 | crop->c.width); | ||
832 | if (ret != 0) { | ||
833 | ret = -EINVAL; | ||
834 | break; | ||
835 | } | ||
836 | ret = pvr2_ctrl_set_value( | ||
837 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), | ||
838 | crop->c.height); | ||
839 | if (ret != 0) { | ||
840 | ret = -EINVAL; | ||
841 | break; | ||
842 | } | ||
843 | } | ||
758 | case VIDIOC_LOG_STATUS: | 844 | case VIDIOC_LOG_STATUS: |
759 | { | 845 | { |
760 | pvr2_hdw_trigger_module_log(hdw); | 846 | pvr2_hdw_trigger_module_log(hdw); |