diff options
Diffstat (limited to 'drivers/media/platform/vimc/vimc-capture.c')
-rw-r--r-- | drivers/media/platform/vimc/vimc-capture.c | 117 |
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 | ||
43 | static 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 | |||
43 | struct vimc_cap_buffer { | 51 | struct 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 | ||
76 | static int vimc_cap_fmt_vid_cap(struct file *file, void *priv, | 84 | static 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 | ||
94 | static 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 | |||
123 | static 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 | |||
86 | static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv, | 153 | static 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 | |||
166 | static 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 = { | |||
110 | static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = { | 200 | static 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; |