diff options
-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); |