diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-08-25 10:46:54 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 23:19:06 -0400 |
commit | 08590b9613f7f624fe3a052586eea2dbb3584b38 (patch) | |
tree | a893d250a4edf84e93794be59e2b1d859314c972 /drivers/media/video/sh_mobile_ceu_camera.c | |
parent | 961801bbb3448a86f0cc93747cecbfae686d81d1 (diff) |
V4L/DVB (12529): soc-camera: switch to s_crop v4l2-subdev video operation
Remove set_crop soc-camera device method and switch to s_crop from v4l2-subdev
video operations. Also extend non-i2c drivers to also hold a pointer to their
v4l2-subdev instance in control device driver-data, i.e., in
dev_get_drvdata((struct device *)to_soc_camera_control(icd))
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/sh_mobile_ceu_camera.c')
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 110 |
1 files changed, 57 insertions, 53 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 499d1a235fd7..726cf0e4dc23 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -846,12 +846,16 @@ static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) | |||
846 | * 3. if (2) failed, try to request the maximum image | 846 | * 3. if (2) failed, try to request the maximum image |
847 | */ | 847 | */ |
848 | static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | 848 | static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, |
849 | struct v4l2_rect *rect) | 849 | struct v4l2_crop *a) |
850 | { | 850 | { |
851 | struct v4l2_rect *rect = &a->c; | ||
851 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 852 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
852 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 853 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
853 | struct v4l2_rect cam_rect, target, cam_max; | 854 | struct v4l2_crop cam_crop; |
855 | struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max; | ||
854 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 856 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
857 | struct device *control = to_soc_camera_control(icd); | ||
858 | struct v4l2_subdev *sd = dev_get_drvdata(control); | ||
855 | unsigned int hscale = pcdev->cflcr & 0xffff; | 859 | unsigned int hscale = pcdev->cflcr & 0xffff; |
856 | unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; | 860 | unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; |
857 | unsigned short width, height; | 861 | unsigned short width, height; |
@@ -859,80 +863,80 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
859 | int ret; | 863 | int ret; |
860 | 864 | ||
861 | /* Scale back up into client units */ | 865 | /* Scale back up into client units */ |
862 | cam_rect.left = size_src(rect->left, hscale); | 866 | cam_rect->left = size_src(rect->left, hscale); |
863 | cam_rect.width = size_src(rect->width, hscale); | 867 | cam_rect->width = size_src(rect->width, hscale); |
864 | cam_rect.top = size_src(rect->top, vscale); | 868 | cam_rect->top = size_src(rect->top, vscale); |
865 | cam_rect.height = size_src(rect->height, vscale); | 869 | cam_rect->height = size_src(rect->height, vscale); |
866 | 870 | ||
867 | target = cam_rect; | 871 | target = *cam_rect; |
868 | 872 | ||
869 | capsr = capture_save_reset(pcdev); | 873 | capsr = capture_save_reset(pcdev); |
870 | dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); | 874 | dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); |
871 | 875 | ||
872 | /* First attempt - see if the client can deliver a perfect result */ | 876 | /* First attempt - see if the client can deliver a perfect result */ |
873 | ret = icd->ops->set_crop(icd, &cam_rect); | 877 | ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); |
874 | if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { | 878 | if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { |
875 | dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", | 879 | dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", |
876 | cam_rect.width, cam_rect.height, | 880 | cam_rect->width, cam_rect->height, |
877 | cam_rect.left, cam_rect.top); | 881 | cam_rect->left, cam_rect->top); |
878 | goto ceu_set_rect; | 882 | goto ceu_set_rect; |
879 | } | 883 | } |
880 | 884 | ||
881 | /* Try to fix cropping, that camera hasn't managed to do */ | 885 | /* Try to fix cropping, that camera hasn't managed to do */ |
882 | dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" | 886 | dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" |
883 | " to %ux%u@%u:%u\n", | 887 | " to %ux%u@%u:%u\n", |
884 | ret, cam_rect.width, cam_rect.height, | 888 | ret, cam_rect->width, cam_rect->height, |
885 | cam_rect.left, cam_rect.top, | 889 | cam_rect->left, cam_rect->top, |
886 | target.width, target.height, target.left, target.top); | 890 | target.width, target.height, target.left, target.top); |
887 | 891 | ||
888 | /* | 892 | /* |
889 | * Popular special case - some cameras can only handle fixed sizes like | 893 | * Popular special case - some cameras can only handle fixed sizes like |
890 | * QVGA, VGA,... Take care to avoid infinite loop. | 894 | * QVGA, VGA,... Take care to avoid infinite loop. |
891 | */ | 895 | */ |
892 | width = max(cam_rect.width, 1); | 896 | width = max(cam_rect->width, 1); |
893 | height = max(cam_rect.height, 1); | 897 | height = max(cam_rect->height, 1); |
894 | cam_max.width = size_src(icd->rect_max.width, hscale); | 898 | cam_max.width = size_src(icd->rect_max.width, hscale); |
895 | cam_max.left = size_src(icd->rect_max.left, hscale); | 899 | cam_max.left = size_src(icd->rect_max.left, hscale); |
896 | cam_max.height = size_src(icd->rect_max.height, vscale); | 900 | cam_max.height = size_src(icd->rect_max.height, vscale); |
897 | cam_max.top = size_src(icd->rect_max.top, vscale); | 901 | cam_max.top = size_src(icd->rect_max.top, vscale); |
898 | while (!ret && (is_smaller(&cam_rect, &target) || | 902 | while (!ret && (is_smaller(cam_rect, &target) || |
899 | is_inside(&cam_rect, &target)) && | 903 | is_inside(cam_rect, &target)) && |
900 | cam_max.width >= width && cam_max.height >= height) { | 904 | cam_max.width >= width && cam_max.height >= height) { |
901 | 905 | ||
902 | width *= 2; | 906 | width *= 2; |
903 | height *= 2; | 907 | height *= 2; |
904 | cam_rect.width = width; | 908 | cam_rect->width = width; |
905 | cam_rect.height = height; | 909 | cam_rect->height = height; |
906 | 910 | ||
907 | /* We do not know what the camera is capable of, play safe */ | 911 | /* We do not know what the camera is capable of, play safe */ |
908 | if (cam_rect.left > target.left) | 912 | if (cam_rect->left > target.left) |
909 | cam_rect.left = cam_max.left; | 913 | cam_rect->left = cam_max.left; |
910 | 914 | ||
911 | if (cam_rect.left + cam_rect.width < target.left + target.width) | 915 | if (cam_rect->left + cam_rect->width < target.left + target.width) |
912 | cam_rect.width = target.left + target.width - | 916 | cam_rect->width = target.left + target.width - |
913 | cam_rect.left; | 917 | cam_rect->left; |
914 | 918 | ||
915 | if (cam_rect.top > target.top) | 919 | if (cam_rect->top > target.top) |
916 | cam_rect.top = cam_max.top; | 920 | cam_rect->top = cam_max.top; |
917 | 921 | ||
918 | if (cam_rect.top + cam_rect.height < target.top + target.height) | 922 | if (cam_rect->top + cam_rect->height < target.top + target.height) |
919 | cam_rect.height = target.top + target.height - | 923 | cam_rect->height = target.top + target.height - |
920 | cam_rect.top; | 924 | cam_rect->top; |
921 | 925 | ||
922 | if (cam_rect.width + cam_rect.left > | 926 | if (cam_rect->width + cam_rect->left > |
923 | cam_max.width + cam_max.left) | 927 | cam_max.width + cam_max.left) |
924 | cam_rect.left = max(cam_max.width + cam_max.left - | 928 | cam_rect->left = max(cam_max.width + cam_max.left - |
925 | cam_rect.width, cam_max.left); | 929 | cam_rect->width, cam_max.left); |
926 | 930 | ||
927 | if (cam_rect.height + cam_rect.top > | 931 | if (cam_rect->height + cam_rect->top > |
928 | cam_max.height + cam_max.top) | 932 | cam_max.height + cam_max.top) |
929 | cam_rect.top = max(cam_max.height + cam_max.top - | 933 | cam_rect->top = max(cam_max.height + cam_max.top - |
930 | cam_rect.height, cam_max.top); | 934 | cam_rect->height, cam_max.top); |
931 | 935 | ||
932 | ret = icd->ops->set_crop(icd, &cam_rect); | 936 | ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); |
933 | dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", | 937 | dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", |
934 | ret, cam_rect.width, cam_rect.height, | 938 | ret, cam_rect->width, cam_rect->height, |
935 | cam_rect.left, cam_rect.top); | 939 | cam_rect->left, cam_rect->top); |
936 | } | 940 | } |
937 | 941 | ||
938 | /* | 942 | /* |
@@ -941,30 +945,30 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
941 | */ | 945 | */ |
942 | if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || | 946 | if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || |
943 | is_inside(&icd->rect_current, rect))) || | 947 | is_inside(&icd->rect_current, rect))) || |
944 | is_smaller(&cam_rect, &target) || is_inside(&cam_rect, &target)) { | 948 | is_smaller(cam_rect, &target) || is_inside(cam_rect, &target)) { |
945 | /* | 949 | /* |
946 | * The camera failed to configure a suitable cropping, | 950 | * The camera failed to configure a suitable cropping, |
947 | * we cannot use the current rectangle, set to max | 951 | * we cannot use the current rectangle, set to max |
948 | */ | 952 | */ |
949 | cam_rect = cam_max; | 953 | *cam_rect = cam_max; |
950 | ret = icd->ops->set_crop(icd, &cam_rect); | 954 | ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); |
951 | dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", | 955 | dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", |
952 | ret, cam_rect.width, cam_rect.height, | 956 | ret, cam_rect->width, cam_rect->height, |
953 | cam_rect.left, cam_rect.top); | 957 | cam_rect->left, cam_rect->top); |
954 | if (ret < 0) | 958 | if (ret < 0 && ret != -ENOIOCTLCMD) |
955 | /* All failed, hopefully resume current capture */ | 959 | /* All failed, hopefully resume current capture */ |
956 | goto resume_capture; | 960 | goto resume_capture; |
957 | 961 | ||
958 | /* Finally, adjust the target rectangle */ | 962 | /* Finally, adjust the target rectangle */ |
959 | if (target.width > cam_rect.width) | 963 | if (target.width > cam_rect->width) |
960 | target.width = cam_rect.width; | 964 | target.width = cam_rect->width; |
961 | if (target.height > cam_rect.height) | 965 | if (target.height > cam_rect->height) |
962 | target.height = cam_rect.height; | 966 | target.height = cam_rect->height; |
963 | if (target.left + target.width > cam_rect.left + cam_rect.width) | 967 | if (target.left + target.width > cam_rect->left + cam_rect->width) |
964 | target.left = cam_rect.left + cam_rect.width - | 968 | target.left = cam_rect->left + cam_rect->width - |
965 | target.width; | 969 | target.width; |
966 | if (target.top + target.height > cam_rect.top + cam_rect.height) | 970 | if (target.top + target.height > cam_rect->top + cam_rect->height) |
967 | target.top = cam_rect.top + cam_rect.height - | 971 | target.top = cam_rect->top + cam_rect->height - |
968 | target.height; | 972 | target.height; |
969 | } | 973 | } |
970 | 974 | ||
@@ -978,14 +982,14 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
978 | */ | 982 | */ |
979 | dev_dbg(&icd->dev, | 983 | dev_dbg(&icd->dev, |
980 | "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", | 984 | "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", |
981 | cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, | 985 | cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, |
982 | target.width, target.height, target.left, target.top, | 986 | target.width, target.height, target.left, target.top, |
983 | rect->width, rect->height, rect->left, rect->top); | 987 | rect->width, rect->height, rect->left, rect->top); |
984 | 988 | ||
985 | ret = 0; | 989 | ret = 0; |
986 | 990 | ||
987 | ceu_set_rect: | 991 | ceu_set_rect: |
988 | cam->camera_rect = cam_rect; | 992 | cam->camera_rect = *cam_rect; |
989 | 993 | ||
990 | rect->width = size_dst(target.width, hscale); | 994 | rect->width = size_dst(target.width, hscale); |
991 | rect->left = size_dst(target.left, hscale); | 995 | rect->left = size_dst(target.left, hscale); |