aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2/pvrusb2-hdw.c
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/pvrusb2-hdw.c
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/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{