aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2
diff options
context:
space:
mode:
authorMike Isely <isely@pobox.com>2008-08-31 20:02:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:36:57 -0400
commit432907f750b27aa2b41e1bf398e6eb711ead448f (patch)
tree6738e7e4650b216724971587efa90581ba4c85aa /drivers/media/video/pvrusb2
parent0b7c2c9598e7447ad6a9d157491e6c5459ae56de (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.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);