aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2/pvrusb2-hdw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-hdw.c')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c311
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);
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{