X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=drivers%2Fmedia%2Fplatform%2Fsoc_camera%2Fsoc_scale_crop.c;h=f77252d6ccd3a3c3caade41b2be891e5ddb4ed47;hb=22db73f6a29cd08748ffbdcca423edcc32edd843;hp=bda29bc1b9331c803702b3685df3a66b733c0e35;hpb=3e5f206c00f73f535c914eedc8b91f424c5a14ab;p=deliverable%2Flinux.git diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c index bda29bc1b933..f77252d6ccd3 100644 --- a/drivers/media/platform/soc_camera/soc_scale_crop.c +++ b/drivers/media/platform/soc_camera/soc_scale_crop.c @@ -40,24 +40,22 @@ static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2) /* Get and store current client crop */ int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) { - struct v4l2_crop crop; - struct v4l2_cropcap cap; + struct v4l2_subdev_selection sdsel = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .target = V4L2_SEL_TGT_CROP, + }; int ret; - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, g_crop, &crop); + ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel); if (!ret) { - *rect = crop.c; + *rect = sdsel.r; return ret; } - /* Camera driver doesn't support .g_crop(), assume default rectangle */ - cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, cropcap, &cap); + sdsel.target = V4L2_SEL_TGT_CROP_DEFAULT; + ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel); if (!ret) - *rect = cap.defrect; + *rect = sdsel.r; return ret; } @@ -93,17 +91,27 @@ static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect) * 2. if (1) failed, try to double the client image until we get one big enough * 3. if (2) failed, try to request the maximum image */ -int soc_camera_client_s_crop(struct v4l2_subdev *sd, - struct v4l2_crop *crop, struct v4l2_crop *cam_crop, +int soc_camera_client_s_selection(struct v4l2_subdev *sd, + struct v4l2_selection *sel, struct v4l2_selection *cam_sel, struct v4l2_rect *target_rect, struct v4l2_rect *subrect) { - struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; + struct v4l2_subdev_selection sdsel = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .target = sel->target, + .flags = sel->flags, + .r = sel->r, + }; + struct v4l2_subdev_selection bounds = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .target = V4L2_SEL_TGT_CROP_BOUNDS, + }; + struct v4l2_rect *rect = &sel->r, *cam_rect = &cam_sel->r; struct device *dev = sd->v4l2_dev->dev; - struct v4l2_cropcap cap; int ret; unsigned int width, height; - v4l2_subdev_call(sd, video, s_crop, crop); + v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel); + sel->r = sdsel.r; ret = soc_camera_client_g_rect(sd, cam_rect); if (ret < 0) return ret; @@ -113,29 +121,29 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd, * be within camera cropcap bounds */ if (!memcmp(rect, cam_rect, sizeof(*rect))) { - /* Even if camera S_CROP failed, but camera rectangle matches */ - dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", + /* Even if camera S_SELECTION failed, but camera rectangle matches */ + dev_dbg(dev, "Camera S_SELECTION successful for %dx%d@%d:%d\n", rect->width, rect->height, rect->left, rect->top); *target_rect = *cam_rect; return 0; } /* Try to fix cropping, that camera hasn't managed to set */ - dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", + dev_geo(dev, "Fix camera S_SELECTION for %dx%d@%d:%d to %dx%d@%d:%d\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, rect->width, rect->height, rect->left, rect->top); /* We need sensor maximum rectangle */ - ret = v4l2_subdev_call(sd, video, cropcap, &cap); + ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &bounds); if (ret < 0) return ret; /* Put user requested rectangle within sensor bounds */ - soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, - cap.bounds.width); - soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, - cap.bounds.height); + soc_camera_limit_side(&rect->left, &rect->width, sdsel.r.left, 2, + bounds.r.width); + soc_camera_limit_side(&rect->top, &rect->height, sdsel.r.top, 4, + bounds.r.height); /* * Popular special case - some cameras can only handle fixed sizes like @@ -150,7 +158,7 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd, */ while (!ret && (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) && - (cap.bounds.width > width || cap.bounds.height > height)) { + (bounds.r.width > width || bounds.r.height > height)) { width *= 2; height *= 2; @@ -168,36 +176,40 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd, * Instead we just drop to the left and top bounds. */ if (cam_rect->left > rect->left) - cam_rect->left = cap.bounds.left; + cam_rect->left = bounds.r.left; if (cam_rect->left + cam_rect->width < rect->left + rect->width) cam_rect->width = rect->left + rect->width - cam_rect->left; if (cam_rect->top > rect->top) - cam_rect->top = cap.bounds.top; + cam_rect->top = bounds.r.top; if (cam_rect->top + cam_rect->height < rect->top + rect->height) cam_rect->height = rect->top + rect->height - cam_rect->top; - v4l2_subdev_call(sd, video, s_crop, cam_crop); + sdsel.r = *cam_rect; + v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel); + *cam_rect = sdsel.r; ret = soc_camera_client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, + dev_geo(dev, "Camera S_SELECTION %d for %dx%d@%d:%d\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } - /* S_CROP must not modify the rectangle */ + /* S_SELECTION must not modify the rectangle */ if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { /* * The camera failed to configure a suitable cropping, * we cannot use the current rectangle, set to max */ - *cam_rect = cap.bounds; - v4l2_subdev_call(sd, video, s_crop, cam_crop); + sdsel.r = bounds.r; + v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel); + *cam_rect = sdsel.r; + ret = soc_camera_client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, + dev_geo(dev, "Camera S_SELECTION %d for max %dx%d@%d:%d\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } @@ -209,7 +221,7 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd, return ret; } -EXPORT_SYMBOL(soc_camera_client_s_crop); +EXPORT_SYMBOL(soc_camera_client_s_selection); /* Iterative set_fmt, also updates cached client crop on success */ static int client_set_fmt(struct soc_camera_device *icd, @@ -221,7 +233,10 @@ static int client_set_fmt(struct soc_camera_device *icd, struct device *dev = icd->parent; struct v4l2_mbus_framefmt *mf = &format->format; unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; - struct v4l2_cropcap cap; + struct v4l2_subdev_selection sdsel = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .target = V4L2_SEL_TGT_CROP_BOUNDS, + }; bool host_1to1; int ret; @@ -243,16 +258,14 @@ static int client_set_fmt(struct soc_camera_device *icd, if (!host_can_scale) goto update_cache; - cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, cropcap, &cap); + ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel); if (ret < 0) return ret; - if (max_width > cap.bounds.width) - max_width = cap.bounds.width; - if (max_height > cap.bounds.height) - max_height = cap.bounds.height; + if (max_width > sdsel.r.width) + max_width = sdsel.r.width; + if (max_height > sdsel.r.height) + max_height = sdsel.r.height; /* Camera set a format, but geometry is not precise, try to improve */ tmp_w = mf->width;