diff options
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-hdw.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 311 |
1 files changed, 264 insertions, 47 deletions
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 | { |