diff options
Diffstat (limited to 'drivers/media/video/sh_vou.c')
-rw-r--r-- | drivers/media/video/sh_vou.c | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c index f5b892a2a8ee..d394187eb701 100644 --- a/drivers/media/video/sh_vou.c +++ b/drivers/media/video/sh_vou.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/version.h> | 22 | #include <linux/version.h> |
22 | #include <linux/videodev2.h> | 23 | #include <linux/videodev2.h> |
23 | 24 | ||
@@ -57,7 +58,7 @@ enum sh_vou_status { | |||
57 | }; | 58 | }; |
58 | 59 | ||
59 | #define VOU_MAX_IMAGE_WIDTH 720 | 60 | #define VOU_MAX_IMAGE_WIDTH 720 |
60 | #define VOU_MAX_IMAGE_HEIGHT 480 | 61 | #define VOU_MAX_IMAGE_HEIGHT 576 |
61 | 62 | ||
62 | struct sh_vou_device { | 63 | struct sh_vou_device { |
63 | struct v4l2_device v4l2_dev; | 64 | struct v4l2_device v4l2_dev; |
@@ -527,20 +528,17 @@ struct sh_vou_geometry { | |||
527 | static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | 528 | static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) |
528 | { | 529 | { |
529 | /* The compiler cannot know, that best and idx will indeed be set */ | 530 | /* The compiler cannot know, that best and idx will indeed be set */ |
530 | unsigned int best_err = UINT_MAX, best = 0, width_max, height_max; | 531 | unsigned int best_err = UINT_MAX, best = 0, img_height_max; |
531 | int i, idx = 0; | 532 | int i, idx = 0; |
532 | 533 | ||
533 | if (std & V4L2_STD_525_60) { | 534 | if (std & V4L2_STD_525_60) |
534 | width_max = 858; | 535 | img_height_max = 480; |
535 | height_max = 262; | 536 | else |
536 | } else { | 537 | img_height_max = 576; |
537 | width_max = 864; | ||
538 | height_max = 312; | ||
539 | } | ||
540 | 538 | ||
541 | /* Image width must be a multiple of 4 */ | 539 | /* Image width must be a multiple of 4 */ |
542 | v4l_bound_align_image(&geo->in_width, 0, VOU_MAX_IMAGE_WIDTH, 2, | 540 | v4l_bound_align_image(&geo->in_width, 0, VOU_MAX_IMAGE_WIDTH, 2, |
543 | &geo->in_height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | 541 | &geo->in_height, 0, img_height_max, 1, 0); |
544 | 542 | ||
545 | /* Select scales to come as close as possible to the output image */ | 543 | /* Select scales to come as close as possible to the output image */ |
546 | for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) { | 544 | for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) { |
@@ -573,7 +571,7 @@ static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
573 | unsigned int found = geo->output.height * vou_scale_v_den[i] / | 571 | unsigned int found = geo->output.height * vou_scale_v_den[i] / |
574 | vou_scale_v_num[i]; | 572 | vou_scale_v_num[i]; |
575 | 573 | ||
576 | if (found > VOU_MAX_IMAGE_HEIGHT) | 574 | if (found > img_height_max) |
577 | /* scales increase */ | 575 | /* scales increase */ |
578 | break; | 576 | break; |
579 | 577 | ||
@@ -597,15 +595,18 @@ static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
597 | */ | 595 | */ |
598 | static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) | 596 | static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) |
599 | { | 597 | { |
600 | unsigned int best_err = UINT_MAX, best, width_max, height_max; | 598 | unsigned int best_err = UINT_MAX, best, width_max, height_max, |
599 | img_height_max; | ||
601 | int i, idx; | 600 | int i, idx; |
602 | 601 | ||
603 | if (std & V4L2_STD_525_60) { | 602 | if (std & V4L2_STD_525_60) { |
604 | width_max = 858; | 603 | width_max = 858; |
605 | height_max = 262 * 2; | 604 | height_max = 262 * 2; |
605 | img_height_max = 480; | ||
606 | } else { | 606 | } else { |
607 | width_max = 864; | 607 | width_max = 864; |
608 | height_max = 312 * 2; | 608 | height_max = 312 * 2; |
609 | img_height_max = 576; | ||
609 | } | 610 | } |
610 | 611 | ||
611 | /* Select scales to come as close as possible to the output image */ | 612 | /* Select scales to come as close as possible to the output image */ |
@@ -644,7 +645,7 @@ static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
644 | unsigned int found = geo->in_height * vou_scale_v_num[i] / | 645 | unsigned int found = geo->in_height * vou_scale_v_num[i] / |
645 | vou_scale_v_den[i]; | 646 | vou_scale_v_den[i]; |
646 | 647 | ||
647 | if (found > VOU_MAX_IMAGE_HEIGHT) | 648 | if (found > img_height_max) |
648 | /* scales increase */ | 649 | /* scales increase */ |
649 | break; | 650 | break; |
650 | 651 | ||
@@ -673,11 +674,12 @@ static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | |||
673 | struct video_device *vdev = video_devdata(file); | 674 | struct video_device *vdev = video_devdata(file); |
674 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | 675 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); |
675 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | 676 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
677 | unsigned int img_height_max; | ||
676 | int pix_idx; | 678 | int pix_idx; |
677 | struct sh_vou_geometry geo; | 679 | struct sh_vou_geometry geo; |
678 | struct v4l2_mbus_framefmt mbfmt = { | 680 | struct v4l2_mbus_framefmt mbfmt = { |
679 | /* Revisit: is this the correct code? */ | 681 | /* Revisit: is this the correct code? */ |
680 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | 682 | .code = V4L2_MBUS_FMT_YUYV8_2X8, |
681 | .field = V4L2_FIELD_INTERLACED, | 683 | .field = V4L2_FIELD_INTERLACED, |
682 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | 684 | .colorspace = V4L2_COLORSPACE_SMPTE170M, |
683 | }; | 685 | }; |
@@ -701,9 +703,14 @@ static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | |||
701 | if (pix_idx == ARRAY_SIZE(vou_fmt)) | 703 | if (pix_idx == ARRAY_SIZE(vou_fmt)) |
702 | return -EINVAL; | 704 | return -EINVAL; |
703 | 705 | ||
706 | if (vou_dev->std & V4L2_STD_525_60) | ||
707 | img_height_max = 480; | ||
708 | else | ||
709 | img_height_max = 576; | ||
710 | |||
704 | /* Image width must be a multiple of 4 */ | 711 | /* Image width must be a multiple of 4 */ |
705 | v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 2, | 712 | v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 2, |
706 | &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | 713 | &pix->height, 0, img_height_max, 1, 0); |
707 | 714 | ||
708 | geo.in_width = pix->width; | 715 | geo.in_width = pix->width; |
709 | geo.in_height = pix->height; | 716 | geo.in_height = pix->height; |
@@ -724,8 +731,8 @@ static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | |||
724 | 731 | ||
725 | /* Sanity checks */ | 732 | /* Sanity checks */ |
726 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || | 733 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || |
727 | (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || | 734 | (unsigned)mbfmt.height > img_height_max || |
728 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | 735 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8) |
729 | return -EIO; | 736 | return -EIO; |
730 | 737 | ||
731 | if (mbfmt.width != geo.output.width || | 738 | if (mbfmt.width != geo.output.width || |
@@ -936,10 +943,11 @@ static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | |||
936 | struct sh_vou_geometry geo; | 943 | struct sh_vou_geometry geo; |
937 | struct v4l2_mbus_framefmt mbfmt = { | 944 | struct v4l2_mbus_framefmt mbfmt = { |
938 | /* Revisit: is this the correct code? */ | 945 | /* Revisit: is this the correct code? */ |
939 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | 946 | .code = V4L2_MBUS_FMT_YUYV8_2X8, |
940 | .field = V4L2_FIELD_INTERLACED, | 947 | .field = V4L2_FIELD_INTERLACED, |
941 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | 948 | .colorspace = V4L2_COLORSPACE_SMPTE170M, |
942 | }; | 949 | }; |
950 | unsigned int img_height_max; | ||
943 | int ret; | 951 | int ret; |
944 | 952 | ||
945 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u@%u:%u\n", __func__, | 953 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u@%u:%u\n", __func__, |
@@ -948,14 +956,19 @@ static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | |||
948 | if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | 956 | if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) |
949 | return -EINVAL; | 957 | return -EINVAL; |
950 | 958 | ||
959 | if (vou_dev->std & V4L2_STD_525_60) | ||
960 | img_height_max = 480; | ||
961 | else | ||
962 | img_height_max = 576; | ||
963 | |||
951 | v4l_bound_align_image(&rect->width, 0, VOU_MAX_IMAGE_WIDTH, 1, | 964 | v4l_bound_align_image(&rect->width, 0, VOU_MAX_IMAGE_WIDTH, 1, |
952 | &rect->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | 965 | &rect->height, 0, img_height_max, 1, 0); |
953 | 966 | ||
954 | if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH) | 967 | if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH) |
955 | rect->left = VOU_MAX_IMAGE_WIDTH - rect->width; | 968 | rect->left = VOU_MAX_IMAGE_WIDTH - rect->width; |
956 | 969 | ||
957 | if (rect->height + rect->top > VOU_MAX_IMAGE_HEIGHT) | 970 | if (rect->height + rect->top > img_height_max) |
958 | rect->top = VOU_MAX_IMAGE_HEIGHT - rect->height; | 971 | rect->top = img_height_max - rect->height; |
959 | 972 | ||
960 | geo.output = *rect; | 973 | geo.output = *rect; |
961 | geo.in_width = pix->width; | 974 | geo.in_width = pix->width; |
@@ -980,8 +993,8 @@ static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | |||
980 | 993 | ||
981 | /* Sanity checks */ | 994 | /* Sanity checks */ |
982 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || | 995 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || |
983 | (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || | 996 | (unsigned)mbfmt.height > img_height_max || |
984 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | 997 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8) |
985 | return -EIO; | 998 | return -EIO; |
986 | 999 | ||
987 | geo.output.width = mbfmt.width; | 1000 | geo.output.width = mbfmt.width; |
@@ -1329,13 +1342,13 @@ static int __devinit sh_vou_probe(struct platform_device *pdev) | |||
1329 | rect->left = 0; | 1342 | rect->left = 0; |
1330 | rect->top = 0; | 1343 | rect->top = 0; |
1331 | rect->width = VOU_MAX_IMAGE_WIDTH; | 1344 | rect->width = VOU_MAX_IMAGE_WIDTH; |
1332 | rect->height = VOU_MAX_IMAGE_HEIGHT; | 1345 | rect->height = 480; |
1333 | pix->width = VOU_MAX_IMAGE_WIDTH; | 1346 | pix->width = VOU_MAX_IMAGE_WIDTH; |
1334 | pix->height = VOU_MAX_IMAGE_HEIGHT; | 1347 | pix->height = 480; |
1335 | pix->pixelformat = V4L2_PIX_FMT_YVYU; | 1348 | pix->pixelformat = V4L2_PIX_FMT_YVYU; |
1336 | pix->field = V4L2_FIELD_NONE; | 1349 | pix->field = V4L2_FIELD_NONE; |
1337 | pix->bytesperline = VOU_MAX_IMAGE_WIDTH * 2; | 1350 | pix->bytesperline = VOU_MAX_IMAGE_WIDTH * 2; |
1338 | pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * VOU_MAX_IMAGE_HEIGHT; | 1351 | pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * 480; |
1339 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; | 1352 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; |
1340 | 1353 | ||
1341 | region = request_mem_region(reg_res->start, resource_size(reg_res), | 1354 | region = request_mem_region(reg_res->start, resource_size(reg_res), |