Lines Matching +full:memcpy +full:- +full:bus +full:- +full:width

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * vimc-scaler.c Virtual Media Controller Driver
5 * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
11 #include <linux/v4l2-mediabus.h>
12 #include <media/v4l2-rect.h>
13 #include <media/v4l2-subdev.h>
15 #include "vimc-common.h"
46 .width = VIMC_SCALER_FMT_WIDTH_DEFAULT,
54 .width = VIMC_SCALER_FMT_WIDTH_DEFAULT,
61 .width = VIMC_FRAME_MIN_WIDTH,
74 .width = sink_fmt->width, in vimc_scaler_get_crop_bound_sink()
75 .height = sink_fmt->height, in vimc_scaler_get_crop_bound_sink()
87 for (i = 0; i < sd->entity.num_pads; i++) { in vimc_scaler_init_state()
102 u32 mbus_code = vimc_mbus_code_by_index(code->index); in vimc_scaler_enum_mbus_code()
106 return -EINVAL; in vimc_scaler_enum_mbus_code()
111 if (!vpix || vpix->bayer) in vimc_scaler_enum_mbus_code()
112 return -EINVAL; in vimc_scaler_enum_mbus_code()
114 code->code = mbus_code; in vimc_scaler_enum_mbus_code()
125 if (fse->index) in vimc_scaler_enum_frame_size()
126 return -EINVAL; in vimc_scaler_enum_frame_size()
129 vpix = vimc_pix_map_by_code(fse->code); in vimc_scaler_enum_frame_size()
130 if (!vpix || vpix->bayer) in vimc_scaler_enum_frame_size()
131 return -EINVAL; in vimc_scaler_enum_frame_size()
133 fse->min_width = VIMC_FRAME_MIN_WIDTH; in vimc_scaler_enum_frame_size()
134 fse->min_height = VIMC_FRAME_MIN_HEIGHT; in vimc_scaler_enum_frame_size()
136 fse->max_width = VIMC_FRAME_MAX_WIDTH; in vimc_scaler_enum_frame_size()
137 fse->max_height = VIMC_FRAME_MAX_HEIGHT; in vimc_scaler_enum_frame_size()
150 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && vscaler->src_frame) in vimc_scaler_set_fmt()
151 return -EBUSY; in vimc_scaler_set_fmt()
153 fmt = v4l2_subdev_state_get_format(sd_state, format->pad); in vimc_scaler_set_fmt()
156 * The media bus code and colorspace can only be changed on the sink in vimc_scaler_set_fmt()
159 if (format->pad == VIMC_SCALER_SINK) { in vimc_scaler_set_fmt()
163 vpix = vimc_pix_map_by_code(format->format.code); in vimc_scaler_set_fmt()
164 if (vpix && !vpix->bayer) in vimc_scaler_set_fmt()
165 fmt->code = format->format.code; in vimc_scaler_set_fmt()
167 fmt->code = fmt_default.code; in vimc_scaler_set_fmt()
170 fmt->colorspace = format->format.colorspace; in vimc_scaler_set_fmt()
171 fmt->ycbcr_enc = format->format.ycbcr_enc; in vimc_scaler_set_fmt()
172 fmt->quantization = format->format.quantization; in vimc_scaler_set_fmt()
173 fmt->xfer_func = format->format.xfer_func; in vimc_scaler_set_fmt()
177 /* Clamp and align the width and height */ in vimc_scaler_set_fmt()
178 fmt->width = clamp_t(u32, format->format.width, VIMC_FRAME_MIN_WIDTH, in vimc_scaler_set_fmt()
180 fmt->height = clamp_t(u32, format->format.height, VIMC_FRAME_MIN_HEIGHT, in vimc_scaler_set_fmt()
187 if (format->pad == VIMC_SCALER_SINK) { in vimc_scaler_set_fmt()
192 crop->width = fmt->width; in vimc_scaler_set_fmt()
193 crop->height = fmt->height; in vimc_scaler_set_fmt()
194 crop->top = 0; in vimc_scaler_set_fmt()
195 crop->left = 0; in vimc_scaler_set_fmt()
201 format->format = *fmt; in vimc_scaler_set_fmt()
212 if (VIMC_IS_SRC(sel->pad)) in vimc_scaler_get_selection()
213 return -EINVAL; in vimc_scaler_get_selection()
215 switch (sel->target) { in vimc_scaler_get_selection()
217 sel->r = *v4l2_subdev_state_get_crop(sd_state, VIMC_SCALER_SINK); in vimc_scaler_get_selection()
221 sel->r = vimc_scaler_get_crop_bound_sink(sink_fmt); in vimc_scaler_get_selection()
224 return -EINVAL; in vimc_scaler_get_selection()
250 if (VIMC_IS_SRC(sel->pad) || sel->target != V4L2_SEL_TGT_CROP) in vimc_scaler_set_selection()
251 return -EINVAL; in vimc_scaler_set_selection()
253 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE && vscaler->src_frame) in vimc_scaler_set_selection()
254 return -EBUSY; in vimc_scaler_set_selection()
258 vimc_scaler_adjust_sink_crop(&sel->r, sink_fmt); in vimc_scaler_set_selection()
259 *crop_rect = sel->r; in vimc_scaler_set_selection()
283 if (vscaler->src_frame) in vimc_scaler_s_stream()
290 vscaler->hw.sink_fmt = *format; in vimc_scaler_s_stream()
291 vscaler->hw.bpp = vimc_pix_map_by_code(format->code)->bpp; in vimc_scaler_s_stream()
295 vscaler->hw.src_fmt = *format; in vimc_scaler_s_stream()
296 frame_size = format->width * format->height * vscaler->hw.bpp; in vimc_scaler_s_stream()
299 vscaler->hw.sink_crop = *rect; in vimc_scaler_s_stream()
307 vscaler->src_frame = vmalloc(frame_size); in vimc_scaler_s_stream()
308 if (!vscaler->src_frame) in vimc_scaler_s_stream()
309 return -ENOMEM; in vimc_scaler_s_stream()
311 if (!vscaler->src_frame) in vimc_scaler_s_stream()
314 vfree(vscaler->src_frame); in vimc_scaler_s_stream()
315 vscaler->src_frame = NULL; in vimc_scaler_s_stream()
337 const struct v4l2_mbus_framefmt *sink_fmt = &vscaler->hw.sink_fmt; in vimc_scaler_fill_src_frame()
338 const struct v4l2_mbus_framefmt *src_fmt = &vscaler->hw.src_fmt; in vimc_scaler_fill_src_frame()
339 const struct v4l2_rect *r = &vscaler->hw.sink_crop; in vimc_scaler_fill_src_frame()
341 u8 *walker = vscaler->src_frame; in vimc_scaler_fill_src_frame()
344 for (src_y = 0; src_y < src_fmt->height; src_y++) { in vimc_scaler_fill_src_frame()
347 snk_y = (src_y * r->height) / src_fmt->height + r->top; in vimc_scaler_fill_src_frame()
348 y_offset = snk_y * sink_fmt->width * vscaler->hw.bpp; in vimc_scaler_fill_src_frame()
350 for (src_x = 0; src_x < src_fmt->width; src_x++) { in vimc_scaler_fill_src_frame()
353 snk_x = (src_x * r->width) / src_fmt->width + r->left; in vimc_scaler_fill_src_frame()
354 x_offset = snk_x * vscaler->hw.bpp; in vimc_scaler_fill_src_frame()
356 memcpy(walker, &sink_frame[index], vscaler->hw.bpp); in vimc_scaler_fill_src_frame()
357 walker += vscaler->hw.bpp; in vimc_scaler_fill_src_frame()
369 if (!vscaler->src_frame) in vimc_scaler_process_frame()
370 return ERR_PTR(-EINVAL); in vimc_scaler_process_frame()
374 return vscaler->src_frame; in vimc_scaler_process_frame()
382 v4l2_subdev_cleanup(&vscaler->sd); in vimc_scaler_release()
383 media_entity_cleanup(vscaler->ved.ent); in vimc_scaler_release()
390 struct v4l2_device *v4l2_dev = &vimc->v4l2_dev; in vimc_scaler_add()
397 return ERR_PTR(-ENOMEM); in vimc_scaler_add()
400 vscaler->pads[VIMC_SCALER_SINK].flags = MEDIA_PAD_FL_SINK; in vimc_scaler_add()
401 vscaler->pads[VIMC_SCALER_SRC].flags = MEDIA_PAD_FL_SOURCE; in vimc_scaler_add()
403 ret = vimc_ent_sd_register(&vscaler->ved, &vscaler->sd, v4l2_dev, in vimc_scaler_add()
406 vscaler->pads, &vimc_scaler_internal_ops, in vimc_scaler_add()
413 vscaler->ved.process_frame = vimc_scaler_process_frame; in vimc_scaler_add()
414 vscaler->ved.dev = vimc->mdev.dev; in vimc_scaler_add()
416 return &vscaler->ved; in vimc_scaler_add()