aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h5
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c311
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h9
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c37
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c86
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);
301static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw);
301 302
302 303
303static void trace_stbit(const char *name,int val) 304static 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
405static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) 406static 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
420static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) 418static 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
436static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) 435static 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
451static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) 447static 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
462static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) 463static 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
479static 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
495static 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
507static 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
519static 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
531static 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
543static 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
555static 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
567static 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
579static 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
591static 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
603static 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
615static 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
3008static 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 */
3024int 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 */
2822int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) 3039int 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 */
175int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); 181int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *);
176 182
183/* Return information about cropping capabilities */
184int 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 */
178int pvr2_hdw_is_hsm(struct pvr2_hdw *); 187int 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
236static void set_crop(struct pvr2_hdw *hdw) 237static 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
268static int check_crop(struct pvr2_hdw *hdw) 255static 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
313void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) 300void 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);