gpio: rcar: Fix runtime PM imbalance on error
[linux/fpc-iii.git] / drivers / media / platform / vimc / vimc-scaler.c
blob7521439747c571b7fb16cf59759582b060571dfb
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * vimc-scaler.c Virtual Media Controller Driver
5 * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
6 */
8 #include <linux/moduleparam.h>
9 #include <linux/vmalloc.h>
10 #include <linux/v4l2-mediabus.h>
11 #include <media/v4l2-rect.h>
12 #include <media/v4l2-subdev.h>
14 #include "vimc-common.h"
16 static unsigned int sca_mult = 3;
17 module_param(sca_mult, uint, 0000);
18 MODULE_PARM_DESC(sca_mult, " the image size multiplier");
20 #define MAX_ZOOM 8
22 #define VIMC_SCA_FMT_WIDTH_DEFAULT 640
23 #define VIMC_SCA_FMT_HEIGHT_DEFAULT 480
25 struct vimc_sca_device {
26 struct vimc_ent_device ved;
27 struct v4l2_subdev sd;
28 /* NOTE: the source fmt is the same as the sink
29 * with the width and hight multiplied by mult
31 struct v4l2_mbus_framefmt sink_fmt;
32 struct v4l2_rect crop_rect;
33 /* Values calculated when the stream starts */
34 u8 *src_frame;
35 unsigned int src_line_size;
36 unsigned int bpp;
37 struct media_pad pads[2];
40 static const struct v4l2_mbus_framefmt sink_fmt_default = {
41 .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
42 .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
43 .code = MEDIA_BUS_FMT_RGB888_1X24,
44 .field = V4L2_FIELD_NONE,
45 .colorspace = V4L2_COLORSPACE_DEFAULT,
48 static const struct v4l2_rect crop_rect_default = {
49 .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
50 .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
51 .top = 0,
52 .left = 0,
55 static const struct v4l2_rect crop_rect_min = {
56 .width = VIMC_FRAME_MIN_WIDTH,
57 .height = VIMC_FRAME_MIN_HEIGHT,
58 .top = 0,
59 .left = 0,
62 static struct v4l2_rect
63 vimc_sca_get_crop_bound_sink(const struct v4l2_mbus_framefmt *sink_fmt)
65 /* Get the crop bounds to clamp the crop rectangle correctly */
66 struct v4l2_rect r = {
67 .left = 0,
68 .top = 0,
69 .width = sink_fmt->width,
70 .height = sink_fmt->height,
72 return r;
75 static void vimc_sca_adjust_sink_crop(struct v4l2_rect *r,
76 const struct v4l2_mbus_framefmt *sink_fmt)
78 const struct v4l2_rect sink_rect =
79 vimc_sca_get_crop_bound_sink(sink_fmt);
81 /* Disallow rectangles smaller than the minimal one. */
82 v4l2_rect_set_min_size(r, &crop_rect_min);
83 v4l2_rect_map_inside(r, &sink_rect);
86 static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
87 struct v4l2_subdev_pad_config *cfg)
89 struct v4l2_mbus_framefmt *mf;
90 struct v4l2_rect *r;
91 unsigned int i;
93 mf = v4l2_subdev_get_try_format(sd, cfg, 0);
94 *mf = sink_fmt_default;
96 r = v4l2_subdev_get_try_crop(sd, cfg, 0);
97 *r = crop_rect_default;
99 for (i = 1; i < sd->entity.num_pads; i++) {
100 mf = v4l2_subdev_get_try_format(sd, cfg, i);
101 *mf = sink_fmt_default;
102 mf->width = mf->width * sca_mult;
103 mf->height = mf->height * sca_mult;
106 return 0;
109 static int vimc_sca_enum_mbus_code(struct v4l2_subdev *sd,
110 struct v4l2_subdev_pad_config *cfg,
111 struct v4l2_subdev_mbus_code_enum *code)
113 const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index);
115 /* We don't support bayer format */
116 if (!vpix || vpix->bayer)
117 return -EINVAL;
119 code->code = vpix->code;
121 return 0;
124 static int vimc_sca_enum_frame_size(struct v4l2_subdev *sd,
125 struct v4l2_subdev_pad_config *cfg,
126 struct v4l2_subdev_frame_size_enum *fse)
128 const struct vimc_pix_map *vpix;
130 if (fse->index)
131 return -EINVAL;
133 /* Only accept code in the pix map table in non bayer format */
134 vpix = vimc_pix_map_by_code(fse->code);
135 if (!vpix || vpix->bayer)
136 return -EINVAL;
138 fse->min_width = VIMC_FRAME_MIN_WIDTH;
139 fse->min_height = VIMC_FRAME_MIN_HEIGHT;
141 if (VIMC_IS_SINK(fse->pad)) {
142 fse->max_width = VIMC_FRAME_MAX_WIDTH;
143 fse->max_height = VIMC_FRAME_MAX_HEIGHT;
144 } else {
145 fse->max_width = VIMC_FRAME_MAX_WIDTH * MAX_ZOOM;
146 fse->max_height = VIMC_FRAME_MAX_HEIGHT * MAX_ZOOM;
149 return 0;
152 static int vimc_sca_get_fmt(struct v4l2_subdev *sd,
153 struct v4l2_subdev_pad_config *cfg,
154 struct v4l2_subdev_format *format)
156 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
157 struct v4l2_rect *crop_rect;
159 /* Get the current sink format */
160 if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
161 format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
162 crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
163 } else {
164 format->format = vsca->sink_fmt;
165 crop_rect = &vsca->crop_rect;
168 /* Scale the frame size for the source pad */
169 if (VIMC_IS_SRC(format->pad)) {
170 format->format.width = crop_rect->width * sca_mult;
171 format->format.height = crop_rect->height * sca_mult;
174 return 0;
177 static void vimc_sca_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
179 const struct vimc_pix_map *vpix;
181 /* Only accept code in the pix map table in non bayer format */
182 vpix = vimc_pix_map_by_code(fmt->code);
183 if (!vpix || vpix->bayer)
184 fmt->code = sink_fmt_default.code;
186 fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
187 VIMC_FRAME_MAX_WIDTH) & ~1;
188 fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
189 VIMC_FRAME_MAX_HEIGHT) & ~1;
191 if (fmt->field == V4L2_FIELD_ANY)
192 fmt->field = sink_fmt_default.field;
194 vimc_colorimetry_clamp(fmt);
197 static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
198 struct v4l2_subdev_pad_config *cfg,
199 struct v4l2_subdev_format *fmt)
201 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
202 struct v4l2_mbus_framefmt *sink_fmt;
203 struct v4l2_rect *crop_rect;
205 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
206 /* Do not change the format while stream is on */
207 if (vsca->src_frame)
208 return -EBUSY;
210 sink_fmt = &vsca->sink_fmt;
211 crop_rect = &vsca->crop_rect;
212 } else {
213 sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
214 crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
218 * Do not change the format of the source pad,
219 * it is propagated from the sink
221 if (VIMC_IS_SRC(fmt->pad)) {
222 fmt->format = *sink_fmt;
223 fmt->format.width = crop_rect->width * sca_mult;
224 fmt->format.height = crop_rect->height * sca_mult;
225 } else {
226 /* Set the new format in the sink pad */
227 vimc_sca_adjust_sink_fmt(&fmt->format);
229 dev_dbg(vsca->ved.dev, "%s: sink format update: "
230 "old:%dx%d (0x%x, %d, %d, %d, %d) "
231 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsca->sd.name,
232 /* old */
233 sink_fmt->width, sink_fmt->height, sink_fmt->code,
234 sink_fmt->colorspace, sink_fmt->quantization,
235 sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
236 /* new */
237 fmt->format.width, fmt->format.height, fmt->format.code,
238 fmt->format.colorspace, fmt->format.quantization,
239 fmt->format.xfer_func, fmt->format.ycbcr_enc);
241 *sink_fmt = fmt->format;
243 /* Do the crop, but respect the current bounds */
244 vimc_sca_adjust_sink_crop(crop_rect, sink_fmt);
247 return 0;
250 static int vimc_sca_get_selection(struct v4l2_subdev *sd,
251 struct v4l2_subdev_pad_config *cfg,
252 struct v4l2_subdev_selection *sel)
254 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
255 struct v4l2_mbus_framefmt *sink_fmt;
256 struct v4l2_rect *crop_rect;
258 if (VIMC_IS_SRC(sel->pad))
259 return -EINVAL;
261 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
262 sink_fmt = &vsca->sink_fmt;
263 crop_rect = &vsca->crop_rect;
264 } else {
265 sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
266 crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
269 switch (sel->target) {
270 case V4L2_SEL_TGT_CROP:
271 sel->r = *crop_rect;
272 break;
273 case V4L2_SEL_TGT_CROP_BOUNDS:
274 sel->r = vimc_sca_get_crop_bound_sink(sink_fmt);
275 break;
276 default:
277 return -EINVAL;
280 return 0;
283 static int vimc_sca_set_selection(struct v4l2_subdev *sd,
284 struct v4l2_subdev_pad_config *cfg,
285 struct v4l2_subdev_selection *sel)
287 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
288 struct v4l2_mbus_framefmt *sink_fmt;
289 struct v4l2_rect *crop_rect;
291 if (VIMC_IS_SRC(sel->pad))
292 return -EINVAL;
294 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
295 /* Do not change the format while stream is on */
296 if (vsca->src_frame)
297 return -EBUSY;
299 crop_rect = &vsca->crop_rect;
300 sink_fmt = &vsca->sink_fmt;
301 } else {
302 crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
303 sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
306 switch (sel->target) {
307 case V4L2_SEL_TGT_CROP:
308 /* Do the crop, but respect the current bounds */
309 vimc_sca_adjust_sink_crop(&sel->r, sink_fmt);
310 *crop_rect = sel->r;
311 break;
312 default:
313 return -EINVAL;
316 return 0;
319 static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = {
320 .init_cfg = vimc_sca_init_cfg,
321 .enum_mbus_code = vimc_sca_enum_mbus_code,
322 .enum_frame_size = vimc_sca_enum_frame_size,
323 .get_fmt = vimc_sca_get_fmt,
324 .set_fmt = vimc_sca_set_fmt,
325 .get_selection = vimc_sca_get_selection,
326 .set_selection = vimc_sca_set_selection,
329 static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
331 struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
333 if (enable) {
334 const struct vimc_pix_map *vpix;
335 unsigned int frame_size;
337 if (vsca->src_frame)
338 return 0;
340 /* Save the bytes per pixel of the sink */
341 vpix = vimc_pix_map_by_code(vsca->sink_fmt.code);
342 vsca->bpp = vpix->bpp;
344 /* Calculate the width in bytes of the src frame */
345 vsca->src_line_size = vsca->crop_rect.width *
346 sca_mult * vsca->bpp;
348 /* Calculate the frame size of the source pad */
349 frame_size = vsca->src_line_size * vsca->crop_rect.height *
350 sca_mult;
352 /* Allocate the frame buffer. Use vmalloc to be able to
353 * allocate a large amount of memory
355 vsca->src_frame = vmalloc(frame_size);
356 if (!vsca->src_frame)
357 return -ENOMEM;
359 } else {
360 if (!vsca->src_frame)
361 return 0;
363 vfree(vsca->src_frame);
364 vsca->src_frame = NULL;
367 return 0;
370 static const struct v4l2_subdev_video_ops vimc_sca_video_ops = {
371 .s_stream = vimc_sca_s_stream,
374 static const struct v4l2_subdev_ops vimc_sca_ops = {
375 .pad = &vimc_sca_pad_ops,
376 .video = &vimc_sca_video_ops,
379 static void vimc_sca_fill_pix(u8 *const ptr,
380 const u8 *const pixel,
381 const unsigned int bpp)
383 unsigned int i;
385 /* copy the pixel to the pointer */
386 for (i = 0; i < bpp; i++)
387 ptr[i] = pixel[i];
390 static void vimc_sca_scale_pix(const struct vimc_sca_device *const vsca,
391 unsigned int lin, unsigned int col,
392 const u8 *const sink_frame)
394 const struct v4l2_rect crop_rect = vsca->crop_rect;
395 unsigned int i, j, index;
396 const u8 *pixel;
398 /* Point to the pixel value in position (lin, col) in the sink frame */
399 index = VIMC_FRAME_INDEX(lin, col,
400 vsca->sink_fmt.width,
401 vsca->bpp);
402 pixel = &sink_frame[index];
404 dev_dbg(vsca->ved.dev,
405 "sca: %s: --- scale_pix sink pos %dx%d, index %d ---\n",
406 vsca->sd.name, lin, col, index);
408 /* point to the place we are going to put the first pixel
409 * in the scaled src frame
411 lin -= crop_rect.top;
412 col -= crop_rect.left;
413 index = VIMC_FRAME_INDEX(lin * sca_mult, col * sca_mult,
414 crop_rect.width * sca_mult, vsca->bpp);
416 dev_dbg(vsca->ved.dev, "sca: %s: scale_pix src pos %dx%d, index %d\n",
417 vsca->sd.name, lin * sca_mult, col * sca_mult, index);
419 /* Repeat this pixel mult times */
420 for (i = 0; i < sca_mult; i++) {
421 /* Iterate through each beginning of a
422 * pixel repetition in a line
424 for (j = 0; j < sca_mult * vsca->bpp; j += vsca->bpp) {
425 dev_dbg(vsca->ved.dev,
426 "sca: %s: sca: scale_pix src pos %d\n",
427 vsca->sd.name, index + j);
429 /* copy the pixel to the position index + j */
430 vimc_sca_fill_pix(&vsca->src_frame[index + j],
431 pixel, vsca->bpp);
434 /* move the index to the next line */
435 index += vsca->src_line_size;
439 static void vimc_sca_fill_src_frame(const struct vimc_sca_device *const vsca,
440 const u8 *const sink_frame)
442 const struct v4l2_rect r = vsca->crop_rect;
443 unsigned int i, j;
445 /* Scale each pixel from the original sink frame */
446 /* TODO: implement scale down, only scale up is supported for now */
447 for (i = r.top; i < r.top + r.height; i++)
448 for (j = r.left; j < r.left + r.width; j++)
449 vimc_sca_scale_pix(vsca, i, j, sink_frame);
452 static void *vimc_sca_process_frame(struct vimc_ent_device *ved,
453 const void *sink_frame)
455 struct vimc_sca_device *vsca = container_of(ved, struct vimc_sca_device,
456 ved);
458 /* If the stream in this node is not active, just return */
459 if (!vsca->src_frame)
460 return ERR_PTR(-EINVAL);
462 vimc_sca_fill_src_frame(vsca, sink_frame);
464 return vsca->src_frame;
467 void vimc_sca_release(struct vimc_ent_device *ved)
469 struct vimc_sca_device *vsca =
470 container_of(ved, struct vimc_sca_device, ved);
472 media_entity_cleanup(vsca->ved.ent);
473 kfree(vsca);
476 struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc,
477 const char *vcfg_name)
479 struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
480 struct vimc_sca_device *vsca;
481 int ret;
483 /* Allocate the vsca struct */
484 vsca = kzalloc(sizeof(*vsca), GFP_KERNEL);
485 if (!vsca)
486 return NULL;
488 /* Initialize ved and sd */
489 vsca->pads[0].flags = MEDIA_PAD_FL_SINK;
490 vsca->pads[1].flags = MEDIA_PAD_FL_SOURCE;
492 ret = vimc_ent_sd_register(&vsca->ved, &vsca->sd, v4l2_dev,
493 vcfg_name,
494 MEDIA_ENT_F_PROC_VIDEO_SCALER, 2,
495 vsca->pads, &vimc_sca_ops);
496 if (ret) {
497 kfree(vsca);
498 return NULL;
501 vsca->ved.process_frame = vimc_sca_process_frame;
502 vsca->ved.dev = vimc->mdev.dev;
504 /* Initialize the frame format */
505 vsca->sink_fmt = sink_fmt_default;
507 /* Initialize the crop selection */
508 vsca->crop_rect = crop_rect_default;
510 return &vsca->ved;