aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/vimc/vimc-capture.c
diff options
context:
space:
mode:
authorHelen Fornazier <helen.koike@collabora.com>2017-06-19 13:00:17 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-06-23 08:07:55 -0400
commit535d296f4841ffbd7f773ff2a559daa6e117f315 (patch)
treefe2bed325075b9e589a17f7b1187453dae1a58fe /drivers/media/platform/vimc/vimc-capture.c
parent88ad71aab1a7931ac3d35c3acaa431c3dc05afd9 (diff)
[media] vimc: cap: Support several image formats
Allow user space to change the image format as the frame size, the pixel format, colorspace, quantization, field YCbCr encoding and the transfer function Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/platform/vimc/vimc-capture.c')
-rw-r--r--drivers/media/platform/vimc/vimc-capture.c117
1 files changed, 101 insertions, 16 deletions
diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c
index 5bdecd103d55..359f59efb44e 100644
--- a/drivers/media/platform/vimc/vimc-capture.c
+++ b/drivers/media/platform/vimc/vimc-capture.c
@@ -40,6 +40,14 @@ struct vimc_cap_device {
40 struct media_pipeline pipe; 40 struct media_pipeline pipe;
41}; 41};
42 42
43static const struct v4l2_pix_format fmt_default = {
44 .width = 640,
45 .height = 480,
46 .pixelformat = V4L2_PIX_FMT_RGB24,
47 .field = V4L2_FIELD_NONE,
48 .colorspace = V4L2_COLORSPACE_DEFAULT,
49};
50
43struct vimc_cap_buffer { 51struct vimc_cap_buffer {
44 /* 52 /*
45 * struct vb2_v4l2_buffer must be the first element 53 * struct vb2_v4l2_buffer must be the first element
@@ -73,7 +81,7 @@ static void vimc_cap_get_format(struct vimc_ent_device *ved,
73 *fmt = vcap->format; 81 *fmt = vcap->format;
74} 82}
75 83
76static int vimc_cap_fmt_vid_cap(struct file *file, void *priv, 84static int vimc_cap_g_fmt_vid_cap(struct file *file, void *priv,
77 struct v4l2_format *f) 85 struct v4l2_format *f)
78{ 86{
79 struct vimc_cap_device *vcap = video_drvdata(file); 87 struct vimc_cap_device *vcap = video_drvdata(file);
@@ -83,16 +91,98 @@ static int vimc_cap_fmt_vid_cap(struct file *file, void *priv,
83 return 0; 91 return 0;
84} 92}
85 93
94static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv,
95 struct v4l2_format *f)
96{
97 struct v4l2_pix_format *format = &f->fmt.pix;
98 const struct vimc_pix_map *vpix;
99
100 format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH,
101 VIMC_FRAME_MAX_WIDTH) & ~1;
102 format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT,
103 VIMC_FRAME_MAX_HEIGHT) & ~1;
104
105 /* Don't accept a pixelformat that is not on the table */
106 vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
107 if (!vpix) {
108 format->pixelformat = fmt_default.pixelformat;
109 vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
110 }
111 /* TODO: Add support for custom bytesperline values */
112 format->bytesperline = format->width * vpix->bpp;
113 format->sizeimage = format->bytesperline * format->height;
114
115 if (format->field == V4L2_FIELD_ANY)
116 format->field = fmt_default.field;
117
118 vimc_colorimetry_clamp(format);
119
120 return 0;
121}
122
123static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv,
124 struct v4l2_format *f)
125{
126 struct vimc_cap_device *vcap = video_drvdata(file);
127
128 /* Do not change the format while stream is on */
129 if (vb2_is_busy(&vcap->queue))
130 return -EBUSY;
131
132 vimc_cap_try_fmt_vid_cap(file, priv, f);
133
134 dev_dbg(vcap->vdev.v4l2_dev->dev, "%s: format update: "
135 "old:%dx%d (0x%x, %d, %d, %d, %d) "
136 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vcap->vdev.name,
137 /* old */
138 vcap->format.width, vcap->format.height,
139 vcap->format.pixelformat, vcap->format.colorspace,
140 vcap->format.quantization, vcap->format.xfer_func,
141 vcap->format.ycbcr_enc,
142 /* new */
143 f->fmt.pix.width, f->fmt.pix.height,
144 f->fmt.pix.pixelformat, f->fmt.pix.colorspace,
145 f->fmt.pix.quantization, f->fmt.pix.xfer_func,
146 f->fmt.pix.ycbcr_enc);
147
148 vcap->format = f->fmt.pix;
149
150 return 0;
151}
152
86static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv, 153static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv,
87 struct v4l2_fmtdesc *f) 154 struct v4l2_fmtdesc *f)
88{ 155{
89 struct vimc_cap_device *vcap = video_drvdata(file); 156 const struct vimc_pix_map *vpix = vimc_pix_map_by_index(f->index);
90 157
91 if (f->index > 0) 158 if (!vpix)
92 return -EINVAL; 159 return -EINVAL;
93 160
94 /* We only support one format for now */ 161 f->pixelformat = vpix->pixelformat;
95 f->pixelformat = vcap->format.pixelformat; 162
163 return 0;
164}
165
166static int vimc_cap_enum_framesizes(struct file *file, void *fh,
167 struct v4l2_frmsizeenum *fsize)
168{
169 const struct vimc_pix_map *vpix;
170
171 if (fsize->index)
172 return -EINVAL;
173
174 /* Only accept code in the pix map table */
175 vpix = vimc_pix_map_by_code(fsize->pixel_format);
176 if (!vpix)
177 return -EINVAL;
178
179 fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
180 fsize->stepwise.min_width = VIMC_FRAME_MIN_WIDTH;
181 fsize->stepwise.max_width = VIMC_FRAME_MAX_WIDTH;
182 fsize->stepwise.min_height = VIMC_FRAME_MIN_HEIGHT;
183 fsize->stepwise.max_height = VIMC_FRAME_MAX_HEIGHT;
184 fsize->stepwise.step_width = 2;
185 fsize->stepwise.step_height = 2;
96 186
97 return 0; 187 return 0;
98} 188}
@@ -110,10 +200,11 @@ static const struct v4l2_file_operations vimc_cap_fops = {
110static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = { 200static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = {
111 .vidioc_querycap = vimc_cap_querycap, 201 .vidioc_querycap = vimc_cap_querycap,
112 202
113 .vidioc_g_fmt_vid_cap = vimc_cap_fmt_vid_cap, 203 .vidioc_g_fmt_vid_cap = vimc_cap_g_fmt_vid_cap,
114 .vidioc_s_fmt_vid_cap = vimc_cap_fmt_vid_cap, 204 .vidioc_s_fmt_vid_cap = vimc_cap_s_fmt_vid_cap,
115 .vidioc_try_fmt_vid_cap = vimc_cap_fmt_vid_cap, 205 .vidioc_try_fmt_vid_cap = vimc_cap_try_fmt_vid_cap,
116 .vidioc_enum_fmt_vid_cap = vimc_cap_enum_fmt_vid_cap, 206 .vidioc_enum_fmt_vid_cap = vimc_cap_enum_fmt_vid_cap,
207 .vidioc_enum_framesizes = vimc_cap_enum_framesizes,
117 208
118 .vidioc_reqbufs = vb2_ioctl_reqbufs, 209 .vidioc_reqbufs = vb2_ioctl_reqbufs,
119 .vidioc_create_bufs = vb2_ioctl_create_bufs, 210 .vidioc_create_bufs = vb2_ioctl_create_bufs,
@@ -360,15 +451,9 @@ struct vimc_ent_device *vimc_cap_create(struct v4l2_device *v4l2_dev,
360 INIT_LIST_HEAD(&vcap->buf_list); 451 INIT_LIST_HEAD(&vcap->buf_list);
361 spin_lock_init(&vcap->qlock); 452 spin_lock_init(&vcap->qlock);
362 453
363 /* Set the frame format (this is hardcoded for now) */ 454 /* Set default frame format */
364 vcap->format.width = 640; 455 vcap->format = fmt_default;
365 vcap->format.height = 480;
366 vcap->format.pixelformat = V4L2_PIX_FMT_RGB24;
367 vcap->format.field = V4L2_FIELD_NONE;
368 vcap->format.colorspace = V4L2_COLORSPACE_SRGB;
369
370 vpix = vimc_pix_map_by_pixelformat(vcap->format.pixelformat); 456 vpix = vimc_pix_map_by_pixelformat(vcap->format.pixelformat);
371
372 vcap->format.bytesperline = vcap->format.width * vpix->bpp; 457 vcap->format.bytesperline = vcap->format.width * vpix->bpp;
373 vcap->format.sizeimage = vcap->format.bytesperline * 458 vcap->format.sizeimage = vcap->format.bytesperline *
374 vcap->format.height; 459 vcap->format.height;