diff options
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-ioctl.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 120 |
1 files changed, 78 insertions, 42 deletions
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index fd6826f472e3..57eb8dfe53fa 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -372,7 +372,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
372 | fmt->fmt.pix.height = itv->main_rect.height; | 372 | fmt->fmt.pix.height = itv->main_rect.height; |
373 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 373 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
374 | fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; | 374 | fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; |
375 | if (itv->output_mode == OUT_UDMA_YUV) { | 375 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
376 | switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { | 376 | switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { |
377 | case IVTV_YUV_MODE_INTERLACED: | 377 | case IVTV_YUV_MODE_INTERLACED: |
378 | fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? | 378 | fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? |
@@ -386,14 +386,13 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
386 | break; | 386 | break; |
387 | } | 387 | } |
388 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; | 388 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; |
389 | fmt->fmt.pix.bytesperline = 720; | ||
390 | fmt->fmt.pix.width = itv->yuv_info.v4l2_src_w; | ||
391 | fmt->fmt.pix.height = itv->yuv_info.v4l2_src_h; | ||
389 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | 392 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ |
390 | fmt->fmt.pix.sizeimage = | 393 | fmt->fmt.pix.sizeimage = |
391 | fmt->fmt.pix.height * fmt->fmt.pix.width + | 394 | 1080 * ((fmt->fmt.pix.height + 31) & ~31); |
392 | fmt->fmt.pix.height * (fmt->fmt.pix.width / 2); | 395 | } else if (streamtype == IVTV_ENC_STREAM_TYPE_YUV) { |
393 | } | ||
394 | else if (itv->output_mode == OUT_YUV || | ||
395 | streamtype == IVTV_ENC_STREAM_TYPE_YUV || | ||
396 | streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
397 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; | 396 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; |
398 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | 397 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ |
399 | fmt->fmt.pix.sizeimage = | 398 | fmt->fmt.pix.sizeimage = |
@@ -490,6 +489,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
490 | static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | 489 | static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, |
491 | struct v4l2_format *fmt, int set_fmt) | 490 | struct v4l2_format *fmt, int set_fmt) |
492 | { | 491 | { |
492 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
493 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | 493 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; |
494 | u16 set; | 494 | u16 set; |
495 | 495 | ||
@@ -505,39 +505,52 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | |||
505 | r.width = fmt->fmt.pix.width; | 505 | r.width = fmt->fmt.pix.width; |
506 | r.height = fmt->fmt.pix.height; | 506 | r.height = fmt->fmt.pix.height; |
507 | ivtv_get_fmt(itv, streamtype, fmt); | 507 | ivtv_get_fmt(itv, streamtype, fmt); |
508 | if (itv->output_mode != OUT_UDMA_YUV) { | 508 | fmt->fmt.pix.width = r.width; |
509 | /* TODO: would setting the rect also be valid for this mode? */ | 509 | fmt->fmt.pix.height = r.height; |
510 | fmt->fmt.pix.width = r.width; | 510 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
511 | fmt->fmt.pix.height = r.height; | ||
512 | } | ||
513 | if (itv->output_mode == OUT_UDMA_YUV) { | ||
514 | /* TODO: add checks for validity */ | ||
515 | fmt->fmt.pix.field = field; | 511 | fmt->fmt.pix.field = field; |
512 | if (fmt->fmt.pix.width < 2) | ||
513 | fmt->fmt.pix.width = 2; | ||
514 | if (fmt->fmt.pix.width > 720) | ||
515 | fmt->fmt.pix.width = 720; | ||
516 | if (fmt->fmt.pix.height < 2) | ||
517 | fmt->fmt.pix.height = 2; | ||
518 | if (fmt->fmt.pix.height > 576) | ||
519 | fmt->fmt.pix.height = 576; | ||
516 | } | 520 | } |
517 | if (set_fmt) { | 521 | if (set_fmt && streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
518 | if (itv->output_mode == OUT_UDMA_YUV) { | 522 | /* Return now if we already have some frame data */ |
519 | switch (field) { | 523 | if (yi->stream_size) |
520 | case V4L2_FIELD_NONE: | 524 | return -EBUSY; |
521 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_PROGRESSIVE; | ||
522 | break; | ||
523 | case V4L2_FIELD_ANY: | ||
524 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_AUTO; | ||
525 | break; | ||
526 | case V4L2_FIELD_INTERLACED_BT: | ||
527 | itv->yuv_info.lace_mode = | ||
528 | IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; | ||
529 | break; | ||
530 | case V4L2_FIELD_INTERLACED_TB: | ||
531 | default: | ||
532 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_INTERLACED; | ||
533 | break; | ||
534 | } | ||
535 | itv->yuv_info.lace_sync_field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; | ||
536 | 525 | ||
537 | /* Force update of yuv registers */ | 526 | yi->v4l2_src_w = r.width; |
538 | itv->yuv_info.yuv_forced_update = 1; | 527 | yi->v4l2_src_h = r.height; |
539 | return 0; | 528 | |
529 | switch (field) { | ||
530 | case V4L2_FIELD_NONE: | ||
531 | yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE; | ||
532 | break; | ||
533 | case V4L2_FIELD_ANY: | ||
534 | yi->lace_mode = IVTV_YUV_MODE_AUTO; | ||
535 | break; | ||
536 | case V4L2_FIELD_INTERLACED_BT: | ||
537 | yi->lace_mode = | ||
538 | IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; | ||
539 | break; | ||
540 | case V4L2_FIELD_INTERLACED_TB: | ||
541 | default: | ||
542 | yi->lace_mode = IVTV_YUV_MODE_INTERLACED; | ||
543 | break; | ||
540 | } | 544 | } |
545 | yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; | ||
546 | |||
547 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | ||
548 | itv->dma_data_req_size = | ||
549 | 1080 * ((yi->v4l2_src_h + 31) & ~31); | ||
550 | |||
551 | /* Force update of yuv registers */ | ||
552 | yi->yuv_forced_update = 1; | ||
553 | return 0; | ||
541 | } | 554 | } |
542 | return 0; | 555 | return 0; |
543 | } | 556 | } |
@@ -703,8 +716,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
703 | { | 716 | { |
704 | struct ivtv_open_id *id = NULL; | 717 | struct ivtv_open_id *id = NULL; |
705 | u32 data[CX2341X_MBOX_MAX_DATA]; | 718 | u32 data[CX2341X_MBOX_MAX_DATA]; |
719 | int streamtype = 0; | ||
706 | 720 | ||
707 | if (filp) id = (struct ivtv_open_id *)filp->private_data; | 721 | if (filp) { |
722 | id = (struct ivtv_open_id *)filp->private_data; | ||
723 | streamtype = id->type; | ||
724 | } | ||
708 | 725 | ||
709 | switch (cmd) { | 726 | switch (cmd) { |
710 | case VIDIOC_G_PRIORITY: | 727 | case VIDIOC_G_PRIORITY: |
@@ -822,6 +839,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
822 | cropcap->bounds.height = itv->is_50hz ? 576 : 480; | 839 | cropcap->bounds.height = itv->is_50hz ? 576 : 480; |
823 | cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; | 840 | cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; |
824 | cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; | 841 | cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; |
842 | } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
843 | cropcap->bounds.width = itv->yuv_info.osd_full_w; | ||
844 | cropcap->bounds.height = itv->yuv_info.osd_full_h; | ||
845 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; | ||
846 | cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; | ||
825 | } else { | 847 | } else { |
826 | cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; | 848 | cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; |
827 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; | 849 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; |
@@ -836,10 +858,15 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
836 | 858 | ||
837 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | 859 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && |
838 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | 860 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { |
839 | if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | 861 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
840 | crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { | 862 | itv->yuv_info.main_rect = crop->c; |
841 | itv->main_rect = crop->c; | ||
842 | return 0; | 863 | return 0; |
864 | } else { | ||
865 | if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | ||
866 | crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { | ||
867 | itv->main_rect = crop->c; | ||
868 | return 0; | ||
869 | } | ||
843 | } | 870 | } |
844 | return -EINVAL; | 871 | return -EINVAL; |
845 | } | 872 | } |
@@ -853,7 +880,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
853 | 880 | ||
854 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | 881 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && |
855 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | 882 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { |
856 | crop->c = itv->main_rect; | 883 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) |
884 | crop->c = itv->yuv_info.main_rect; | ||
885 | else | ||
886 | crop->c = itv->main_rect; | ||
857 | return 0; | 887 | return 0; |
858 | } | 888 | } |
859 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 889 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
@@ -864,7 +894,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
864 | case VIDIOC_ENUM_FMT: { | 894 | case VIDIOC_ENUM_FMT: { |
865 | static struct v4l2_fmtdesc formats[] = { | 895 | static struct v4l2_fmtdesc formats[] = { |
866 | { 0, 0, 0, | 896 | { 0, 0, 0, |
867 | "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, | 897 | "HM12 (YUV 4:2:2)", V4L2_PIX_FMT_HM12, |
868 | { 0, 0, 0, 0 } | 898 | { 0, 0, 0, 0 } |
869 | }, | 899 | }, |
870 | { 1, 0, V4L2_FMT_FLAG_COMPRESSED, | 900 | { 1, 0, V4L2_FMT_FLAG_COMPRESSED, |
@@ -1043,6 +1073,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1043 | itv->main_rect.height = itv->params.height; | 1073 | itv->main_rect.height = itv->params.height; |
1044 | ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | 1074 | ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, |
1045 | 720, itv->main_rect.height, 0, 0); | 1075 | 720, itv->main_rect.height, 0, 0); |
1076 | itv->yuv_info.main_rect = itv->main_rect; | ||
1077 | if (!itv->osd_info) { | ||
1078 | itv->yuv_info.osd_full_w = 720; | ||
1079 | itv->yuv_info.osd_full_h = | ||
1080 | itv->is_out_50hz ? 576 : 480; | ||
1081 | } | ||
1046 | } | 1082 | } |
1047 | break; | 1083 | break; |
1048 | } | 1084 | } |