diff options
Diffstat (limited to 'drivers/media/platform/qcom/camss/camss-video.c')
| -rw-r--r-- | drivers/media/platform/qcom/camss/camss-video.c | 444 |
1 files changed, 121 insertions, 323 deletions
diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index 58aebe7114cd..831486e14754 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -18,218 +18,16 @@ #include "camss-video.h" #include "camss.h" -struct fract { - u8 numerator; - u8 denominator; -}; - -/* - * struct camss_format_info - ISP media bus format information - * @code: V4L2 media bus format code - * @pixelformat: V4L2 pixel format FCC identifier - * @planes: Number of planes - * @hsub: Horizontal subsampling (for each plane) - * @vsub: Vertical subsampling (for each plane) - * @bpp: Bits per pixel when stored in memory (for each plane) - */ -struct camss_format_info { - u32 code; - u32 pixelformat; - u8 planes; - struct fract hsub[3]; - struct fract vsub[3]; - unsigned int bpp[3]; -}; - -static const struct camss_format_info formats_rdi_8x16[] = { - { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_Y10_1X10, V4L2_PIX_FMT_Y10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, -}; - -static const struct camss_format_info formats_rdi_8x96[] = { - { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_PIX_FMT_SBGGR10, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SBGGR14_1X14, V4L2_PIX_FMT_SBGGR14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SGBRG14_1X14, V4L2_PIX_FMT_SGBRG14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SGRBG14_1X14, V4L2_PIX_FMT_SGRBG14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SRGGB14_1X14, V4L2_PIX_FMT_SRGGB14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_Y10_1X10, V4L2_PIX_FMT_Y10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, V4L2_PIX_FMT_Y10, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, -}; - -static const struct camss_format_info formats_pix_8x16[] = { - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, -}; - -static const struct camss_format_info formats_pix_8x96[] = { - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, -}; +#define CAMSS_FRAME_MIN_WIDTH 1 +#define CAMSS_FRAME_MAX_WIDTH 8191 +#define CAMSS_FRAME_MIN_HEIGHT 1 +#define CAMSS_FRAME_MAX_HEIGHT_RDI 8191 +#define CAMSS_FRAME_MAX_HEIGHT_PIX 4096 /* ----------------------------------------------------------------------------- * Helper functions */ -static int video_find_format(u32 code, u32 pixelformat, - const struct camss_format_info *formats, - unsigned int nformats) -{ - int i; - - for (i = 0; i < nformats; i++) { - if (formats[i].code == code && - formats[i].pixelformat == pixelformat) - return i; - } - - for (i = 0; i < nformats; i++) - if (formats[i].code == code) - return i; - - WARN_ON(1); - - return -EINVAL; -} - /* * video_mbus_to_pix_mp - Convert v4l2_mbus_framefmt to v4l2_pix_format_mplane * @mbus: v4l2_mbus_framefmt format (input) @@ -271,7 +69,7 @@ static struct v4l2_subdev *video_remote_subdev(struct camss_video *video, { struct media_pad *remote; - remote = media_entity_remote_pad(&video->pad); + remote = media_pad_remote_pad_first(&video->pad); if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) return NULL; @@ -285,7 +83,9 @@ static struct v4l2_subdev *video_remote_subdev(struct camss_video *video, static int video_get_subdev_format(struct camss_video *video, struct v4l2_format *format) { - struct v4l2_subdev_format fmt; + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; struct v4l2_subdev *subdev; u32 pad; int ret; @@ -295,15 +95,13 @@ static int video_get_subdev_format(struct camss_video *video, return -EPIPE; fmt.pad = pad; - fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); if (ret) return ret; - ret = video_find_format(fmt.format.code, - format->fmt.pix_mp.pixelformat, - video->formats, video->nformats); + ret = camss_format_find_format(fmt.format.code, format->fmt.pix_mp.pixelformat, + video->formats, video->nformats); if (ret < 0) return ret; @@ -427,6 +225,21 @@ static int video_check_format(struct camss_video *video) return 0; } +static int video_prepare_streaming(struct vb2_queue *q) +{ + struct camss_video *video = vb2_get_drv_priv(q); + struct video_device *vdev = &video->vdev; + int ret; + + ret = v4l2_pipeline_pm_get(&vdev->entity); + if (ret < 0) { + dev_err(video->camss->dev, "Failed to power up pipeline: %d\n", + ret); + } + + return ret; +} + static int video_start_streaming(struct vb2_queue *q, unsigned int count) { struct camss_video *video = vb2_get_drv_priv(q); @@ -436,9 +249,11 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) struct v4l2_subdev *subdev; int ret; - ret = media_pipeline_start(&vdev->entity, &video->pipe); - if (ret < 0) - return ret; + ret = video_device_pipeline_alloc_start(vdev); + if (ret < 0) { + dev_err(video->camss->dev, "Failed to start media pipeline: %d\n", ret); + goto flush_buffers; + } ret = video_check_format(video); if (ret < 0) @@ -450,7 +265,7 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) if (!(pad->flags & MEDIA_PAD_FL_SINK)) break; - pad = media_entity_remote_pad(pad); + pad = media_pad_remote_pad_first(pad); if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) break; @@ -465,8 +280,9 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) return 0; error: - media_pipeline_stop(&vdev->entity); + video_device_pipeline_stop(vdev); +flush_buffers: video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED); return ret; @@ -479,6 +295,7 @@ static void video_stop_streaming(struct vb2_queue *q) struct media_entity *entity; struct media_pad *pad; struct v4l2_subdev *subdev; + int ret; entity = &vdev->entity; while (1) { @@ -486,30 +303,43 @@ static void video_stop_streaming(struct vb2_queue *q) if (!(pad->flags & MEDIA_PAD_FL_SINK)) break; - pad = media_entity_remote_pad(pad); + pad = media_pad_remote_pad_first(pad); if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) break; entity = pad->entity; subdev = media_entity_to_v4l2_subdev(entity); - v4l2_subdev_call(subdev, video, s_stream, 0); + ret = v4l2_subdev_call(subdev, video, s_stream, 0); + + if (ret) { + dev_err(video->camss->dev, "Video pipeline stop failed: %d\n", ret); + return; + } } - media_pipeline_stop(&vdev->entity); + video_device_pipeline_stop(vdev); video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR); } +static void video_unprepare_streaming(struct vb2_queue *q) +{ + struct camss_video *video = vb2_get_drv_priv(q); + struct video_device *vdev = &video->vdev; + + v4l2_pipeline_pm_put(&vdev->entity); +} + static const struct vb2_ops msm_video_vb2_q_ops = { .queue_setup = video_queue_setup, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, .buf_init = video_buf_init, .buf_prepare = video_buf_prepare, .buf_queue = video_buf_queue, + .prepare_streaming = video_prepare_streaming, .start_streaming = video_start_streaming, .stop_streaming = video_stop_streaming, + .unprepare_streaming = video_unprepare_streaming, }; /* ----------------------------------------------------------------------------- @@ -519,12 +349,8 @@ static const struct vb2_ops msm_video_vb2_q_ops = { static int video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct camss_video *video = video_drvdata(file); - strscpy(cap->driver, "qcom-camss", sizeof(cap->driver)); strscpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", - dev_name(video->camss->dev)); return 0; } @@ -533,6 +359,7 @@ static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) { struct camss_video *video = video_drvdata(file); int i, j, k; + u32 mcode = f->mbus_code; if (f->type != video->type) return -EINVAL; @@ -540,10 +367,26 @@ static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) if (f->index >= video->nformats) return -EINVAL; - /* find index "i" of "k"th unique pixelformat in formats array */ + /* + * Find index "i" of "k"th unique pixelformat in formats array. + * + * If f->mbus_code passed to video_enum_fmt() is not zero, a device + * with V4L2_CAP_IO_MC capability restricts enumeration to only the + * pixel formats that can be produced from that media bus code. + * This is implemented by skipping video->formats[] entries with + * code != f->mbus_code (if f->mbus_code is not zero). + * If the f->mbus_code passed to video_enum_fmt() is not supported, + * -EINVAL is returned. + * If f->mbus_code is zero, all the pixel formats are enumerated. + */ k = -1; for (i = 0; i < video->nformats; i++) { + if (mcode != 0 && video->formats[i].code != mcode) + continue; + for (j = 0; j < i; j++) { + if (mcode != 0 && video->formats[j].code != mcode) + continue; if (video->formats[i].pixelformat == video->formats[j].pixelformat) break; @@ -556,7 +399,12 @@ static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) break; } - if (k < f->index) + if (k == -1 || k < f->index) + /* + * All the unique pixel formats matching the arguments + * have been enumerated (k >= 0 and f->index > 0), or + * no pixel formats match the non-zero f->mbus_code (k == -1). + */ return -EINVAL; f->pixelformat = video->formats[i].pixelformat; @@ -564,6 +412,36 @@ static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) return 0; } +static int video_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + struct camss_video *video = video_drvdata(file); + int i; + + if (fsize->index) + return -EINVAL; + + /* Only accept pixel format present in the formats[] table */ + for (i = 0; i < video->nformats; i++) { + if (video->formats[i].pixelformat == fsize->pixel_format) + break; + } + + if (i == video->nformats) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + fsize->stepwise.min_width = CAMSS_FRAME_MIN_WIDTH; + fsize->stepwise.max_width = CAMSS_FRAME_MAX_WIDTH; + fsize->stepwise.min_height = CAMSS_FRAME_MIN_HEIGHT; + fsize->stepwise.max_height = (video->line_based) ? + CAMSS_FRAME_MAX_HEIGHT_PIX : CAMSS_FRAME_MAX_HEIGHT_RDI; + fsize->stepwise.step_width = 1; + fsize->stepwise.step_height = 1; + + return 0; +} + static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f) { struct camss_video *video = video_drvdata(file); @@ -593,7 +471,7 @@ static int __video_try_fmt(struct camss_video *video, struct v4l2_format *f) 1, 65528); sizeimage[i] = clamp_t(u32, p->sizeimage, bytesperline[i], - bytesperline[i] * 4096); + bytesperline[i] * CAMSS_FRAME_MAX_HEIGHT_PIX); } for (j = 0; j < video->nformats; j++) @@ -610,8 +488,8 @@ static int __video_try_fmt(struct camss_video *video, struct v4l2_format *f) memset(pix_mp, 0, sizeof(*pix_mp)); pix_mp->pixelformat = fi->pixelformat; - pix_mp->width = clamp_t(u32, width, 1, 8191); - pix_mp->height = clamp_t(u32, height, 1, 8191); + pix_mp->width = clamp_t(u32, width, 1, CAMSS_FRAME_MAX_WIDTH); + pix_mp->height = clamp_t(u32, height, 1, CAMSS_FRAME_MAX_HEIGHT_RDI); pix_mp->num_planes = fi->planes; for (i = 0; i < pix_mp->num_planes; i++) { bpl = pix_mp->width / fi->hsub[i].numerator * @@ -637,7 +515,7 @@ static int __video_try_fmt(struct camss_video *video, struct v4l2_format *f) 1, 65528); p->sizeimage = clamp_t(u32, p->sizeimage, p->bytesperline, - p->bytesperline * 4096); + p->bytesperline * CAMSS_FRAME_MAX_HEIGHT_PIX); lines = p->sizeimage / p->bytesperline; if (p->bytesperline < bytesperline[i]) @@ -703,7 +581,8 @@ static int video_s_input(struct file *file, void *fh, unsigned int input) static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = { .vidioc_querycap = video_querycap, - .vidioc_enum_fmt_vid_cap_mplane = video_enum_fmt, + .vidioc_enum_fmt_vid_cap = video_enum_fmt, + .vidioc_enum_framesizes = video_enum_framesizes, .vidioc_g_fmt_vid_cap_mplane = video_g_fmt, .vidioc_s_fmt_vid_cap_mplane = video_s_fmt, .vidioc_try_fmt_vid_cap_mplane = video_try_fmt, @@ -725,64 +604,11 @@ static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = { * V4L2 file operations */ -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct camss_video *video = video_drvdata(file); - struct v4l2_fh *vfh; - int ret; - - mutex_lock(&video->lock); - - vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); - if (vfh == NULL) { - ret = -ENOMEM; - goto error_alloc; - } - - v4l2_fh_init(vfh, vdev); - v4l2_fh_add(vfh); - - file->private_data = vfh; - - ret = v4l2_pipeline_pm_use(&vdev->entity, 1); - if (ret < 0) { - dev_err(video->camss->dev, "Failed to power up pipeline: %d\n", - ret); - goto error_pm_use; - } - - mutex_unlock(&video->lock); - - return 0; - -error_pm_use: - v4l2_fh_release(file); - -error_alloc: - mutex_unlock(&video->lock); - - return ret; -} - -static int video_release(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - - vb2_fop_release(file); - - v4l2_pipeline_pm_use(&vdev->entity, 0); - - file->private_data = NULL; - - return 0; -} - static const struct v4l2_file_operations msm_vid_fops = { .owner = THIS_MODULE, .unlocked_ioctl = video_ioctl2, - .open = video_open, - .release = video_release, + .open = v4l2_fh_open, + .release = vb2_fop_release, .poll = vb2_fop_poll, .mmap = vb2_fop_mmap, .read = vb2_fop_read, @@ -847,7 +673,7 @@ static int msm_video_init_format(struct camss_video *video) */ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, - const char *name, int is_pix) + const char *name) { struct media_pad *pad = &video->pad; struct video_device *vdev; @@ -879,31 +705,11 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, if (ret < 0) { dev_err(v4l2_dev->dev, "Failed to init video entity: %d\n", ret); - goto error_media_init; + goto error_vb2_init; } mutex_init(&video->lock); - if (video->camss->version == CAMSS_8x16) { - if (is_pix) { - video->formats = formats_pix_8x16; - video->nformats = ARRAY_SIZE(formats_pix_8x16); - } else { - video->formats = formats_rdi_8x16; - video->nformats = ARRAY_SIZE(formats_rdi_8x16); - } - } else if (video->camss->version == CAMSS_8x96) { - if (is_pix) { - video->formats = formats_pix_8x96; - video->nformats = ARRAY_SIZE(formats_pix_8x96); - } else { - video->formats = formats_rdi_8x96; - video->nformats = ARRAY_SIZE(formats_rdi_8x96); - } - } else { - goto error_video_register; - } - ret = msm_video_init_format(video); if (ret < 0) { dev_err(v4l2_dev->dev, "Failed to init format: %d\n", ret); @@ -911,8 +717,8 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, } vdev->fops = &msm_vid_fops; - vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING + | V4L2_CAP_READWRITE | V4L2_CAP_IO_MC; vdev->ioctl_ops = &msm_vid_ioctl_ops; vdev->release = msm_video_release; vdev->v4l2_dev = v4l2_dev; @@ -921,7 +727,7 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, vdev->lock = &video->lock; strscpy(vdev->name, name, sizeof(vdev->name)); - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); if (ret < 0) { dev_err(v4l2_dev->dev, "Failed to register video device: %d\n", ret); @@ -936,23 +742,15 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, error_video_register: media_entity_cleanup(&vdev->entity); mutex_destroy(&video->lock); -error_media_init: - vb2_queue_release(&video->vb2_q); error_vb2_init: mutex_destroy(&video->q_lock); return ret; } -void msm_video_stop_streaming(struct camss_video *video) -{ - if (vb2_is_streaming(&video->vb2_q)) - vb2_queue_release(&video->vb2_q); -} - void msm_video_unregister(struct camss_video *video) { atomic_inc(&video->camss->ref_count); - video_unregister_device(&video->vdev); + vb2_video_unregister_device(&video->vdev); atomic_dec(&video->camss->ref_count); } |
