aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/sh_vou.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/sh_vou.c')
-rw-r--r--drivers/media/video/sh_vou.c65
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
62struct sh_vou_device { 63struct sh_vou_device {
63 struct v4l2_device v4l2_dev; 64 struct v4l2_device v4l2_dev;
@@ -527,20 +528,17 @@ struct sh_vou_geometry {
527static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) 528static 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 */
598static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) 596static 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),