Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * vimc-scaler.c Virtual Media Controller Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/v4l2-mediabus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <media/v4l2-rect.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "vimc-common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) static unsigned int sca_mult = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) module_param(sca_mult, uint, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) MODULE_PARM_DESC(sca_mult, " the image size multiplier");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define MAX_ZOOM	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define VIMC_SCA_FMT_WIDTH_DEFAULT  640
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define VIMC_SCA_FMT_HEIGHT_DEFAULT 480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) struct vimc_sca_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct vimc_ent_device ved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct v4l2_subdev sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	/* NOTE: the source fmt is the same as the sink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	 * with the width and hight multiplied by mult
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	struct v4l2_mbus_framefmt sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	struct v4l2_rect crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	/* Values calculated when the stream starts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	u8 *src_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	unsigned int src_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	unsigned int bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct media_pad pads[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static const struct v4l2_mbus_framefmt sink_fmt_default = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	.width = VIMC_SCA_FMT_WIDTH_DEFAULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	.height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	.code = MEDIA_BUS_FMT_RGB888_1X24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	.field = V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	.colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static const struct v4l2_rect crop_rect_default = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	.width = VIMC_SCA_FMT_WIDTH_DEFAULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	.height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	.top = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	.left = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static const struct v4l2_rect crop_rect_min = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	.width = VIMC_FRAME_MIN_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	.height = VIMC_FRAME_MIN_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	.top = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	.left = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static struct v4l2_rect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) vimc_sca_get_crop_bound_sink(const struct v4l2_mbus_framefmt *sink_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	/* Get the crop bounds to clamp the crop rectangle correctly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	struct v4l2_rect r = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		.left = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		.top = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		.width = sink_fmt->width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		.height = sink_fmt->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static void vimc_sca_adjust_sink_crop(struct v4l2_rect *r,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 				      const struct v4l2_mbus_framefmt *sink_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	const struct v4l2_rect sink_rect =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		vimc_sca_get_crop_bound_sink(sink_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	/* Disallow rectangles smaller than the minimal one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	v4l2_rect_set_min_size(r, &crop_rect_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	v4l2_rect_map_inside(r, &sink_rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 			     struct v4l2_subdev_pad_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	struct v4l2_mbus_framefmt *mf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct v4l2_rect *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	mf = v4l2_subdev_get_try_format(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	*mf = sink_fmt_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	r = v4l2_subdev_get_try_crop(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	*r = crop_rect_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	for (i = 1; i < sd->entity.num_pads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		mf = v4l2_subdev_get_try_format(sd, cfg, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		*mf = sink_fmt_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		mf->width = mf->width * sca_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		mf->height = mf->height * sca_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int vimc_sca_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 				   struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 				   struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	u32 mbus_code = vimc_mbus_code_by_index(code->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	const struct vimc_pix_map *vpix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	if (!mbus_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	vpix = vimc_pix_map_by_code(mbus_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	/* We don't support bayer format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (!vpix || vpix->bayer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	code->code = mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int vimc_sca_enum_frame_size(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 				    struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 				    struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	const struct vimc_pix_map *vpix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (fse->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	/* Only accept code in the pix map table in non bayer format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	vpix = vimc_pix_map_by_code(fse->code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (!vpix || vpix->bayer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	fse->min_width = VIMC_FRAME_MIN_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	fse->min_height = VIMC_FRAME_MIN_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (VIMC_IS_SINK(fse->pad)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		fse->max_width = VIMC_FRAME_MAX_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		fse->max_height = VIMC_FRAME_MAX_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		fse->max_width = VIMC_FRAME_MAX_WIDTH * MAX_ZOOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		fse->max_height = VIMC_FRAME_MAX_HEIGHT * MAX_ZOOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int vimc_sca_get_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			    struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			    struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	struct v4l2_rect *crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	/* Get the current sink format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		format->format = vsca->sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		crop_rect = &vsca->crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	/* Scale the frame size for the source pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (VIMC_IS_SRC(format->pad)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		format->format.width = crop_rect->width * sca_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		format->format.height = crop_rect->height * sca_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void vimc_sca_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	const struct vimc_pix_map *vpix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	/* Only accept code in the pix map table in non bayer format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	vpix = vimc_pix_map_by_code(fmt->code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	if (!vpix || vpix->bayer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		fmt->code = sink_fmt_default.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			     VIMC_FRAME_MAX_WIDTH) & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			      VIMC_FRAME_MAX_HEIGHT) & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	if (fmt->field == V4L2_FIELD_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		fmt->field = sink_fmt_default.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	vimc_colorimetry_clamp(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			    struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			    struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	struct v4l2_mbus_framefmt *sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct v4l2_rect *crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		/* Do not change the format while stream is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		if (vsca->src_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		sink_fmt = &vsca->sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		crop_rect = &vsca->crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	 * Do not change the format of the source pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	 * it is propagated from the sink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (VIMC_IS_SRC(fmt->pad)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		fmt->format = *sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		fmt->format.width = crop_rect->width * sca_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		fmt->format.height = crop_rect->height * sca_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		/* Set the new format in the sink pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		vimc_sca_adjust_sink_fmt(&fmt->format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		dev_dbg(vsca->ved.dev, "%s: sink format update: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			"old:%dx%d (0x%x, %d, %d, %d, %d) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			"new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsca->sd.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			/* old */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 			sink_fmt->width, sink_fmt->height, sink_fmt->code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			sink_fmt->colorspace, sink_fmt->quantization,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			/* new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			fmt->format.width, fmt->format.height, fmt->format.code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			fmt->format.colorspace,	fmt->format.quantization,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			fmt->format.xfer_func, fmt->format.ycbcr_enc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		*sink_fmt = fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		/* Do the crop, but respect the current bounds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		vimc_sca_adjust_sink_crop(crop_rect, sink_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static int vimc_sca_get_selection(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 				  struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 				  struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	struct v4l2_mbus_framefmt *sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	struct v4l2_rect *crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (VIMC_IS_SRC(sel->pad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		sink_fmt = &vsca->sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		crop_rect = &vsca->crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	switch (sel->target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	case V4L2_SEL_TGT_CROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		sel->r = *crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	case V4L2_SEL_TGT_CROP_BOUNDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		sel->r = vimc_sca_get_crop_bound_sink(sink_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int vimc_sca_set_selection(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 				  struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 				  struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	struct v4l2_mbus_framefmt *sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	struct v4l2_rect *crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	if (VIMC_IS_SRC(sel->pad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		/* Do not change the format while stream is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		if (vsca->src_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 			return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		crop_rect = &vsca->crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		sink_fmt = &vsca->sink_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	switch (sel->target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	case V4L2_SEL_TGT_CROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		/* Do the crop, but respect the current bounds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		vimc_sca_adjust_sink_crop(&sel->r, sink_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		*crop_rect = sel->r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	.init_cfg		= vimc_sca_init_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	.enum_mbus_code		= vimc_sca_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	.enum_frame_size	= vimc_sca_enum_frame_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	.get_fmt		= vimc_sca_get_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	.set_fmt		= vimc_sca_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	.get_selection		= vimc_sca_get_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	.set_selection		= vimc_sca_set_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		const struct vimc_pix_map *vpix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		unsigned int frame_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		if (vsca->src_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		/* Save the bytes per pixel of the sink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		vpix = vimc_pix_map_by_code(vsca->sink_fmt.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		vsca->bpp = vpix->bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		/* Calculate the width in bytes of the src frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		vsca->src_line_size = vsca->crop_rect.width *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 				      sca_mult * vsca->bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		/* Calculate the frame size of the source pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		frame_size = vsca->src_line_size * vsca->crop_rect.height *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 			     sca_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		/* Allocate the frame buffer. Use vmalloc to be able to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		 * allocate a large amount of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		vsca->src_frame = vmalloc(frame_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		if (!vsca->src_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		if (!vsca->src_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		vfree(vsca->src_frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		vsca->src_frame = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static const struct v4l2_subdev_video_ops vimc_sca_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	.s_stream = vimc_sca_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static const struct v4l2_subdev_ops vimc_sca_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	.pad = &vimc_sca_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	.video = &vimc_sca_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static void vimc_sca_fill_pix(u8 *const ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 			      const u8 *const pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 			      const unsigned int bpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	/* copy the pixel to the pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	for (i = 0; i < bpp; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		ptr[i] = pixel[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static void vimc_sca_scale_pix(const struct vimc_sca_device *const vsca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			       unsigned int lin, unsigned int col,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			       const u8 *const sink_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	const struct v4l2_rect crop_rect = vsca->crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	unsigned int i, j, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	const u8 *pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	/* Point to the pixel value in position (lin, col) in the sink frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	index = VIMC_FRAME_INDEX(lin, col,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 				 vsca->sink_fmt.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 				 vsca->bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	pixel = &sink_frame[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	dev_dbg(vsca->ved.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		"sca: %s: --- scale_pix sink pos %dx%d, index %d ---\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		vsca->sd.name, lin, col, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	/* point to the place we are going to put the first pixel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	 * in the scaled src frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	lin -= crop_rect.top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	col -= crop_rect.left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	index = VIMC_FRAME_INDEX(lin * sca_mult, col * sca_mult,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 				 crop_rect.width * sca_mult, vsca->bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	dev_dbg(vsca->ved.dev, "sca: %s: scale_pix src pos %dx%d, index %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		vsca->sd.name, lin * sca_mult, col * sca_mult, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	/* Repeat this pixel mult times */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	for (i = 0; i < sca_mult; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		/* Iterate through each beginning of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		 * pixel repetition in a line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		for (j = 0; j < sca_mult * vsca->bpp; j += vsca->bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			dev_dbg(vsca->ved.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 				"sca: %s: sca: scale_pix src pos %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 				vsca->sd.name, index + j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			/* copy the pixel to the position index + j */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 			vimc_sca_fill_pix(&vsca->src_frame[index + j],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 					  pixel, vsca->bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		/* move the index to the next line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		index += vsca->src_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void vimc_sca_fill_src_frame(const struct vimc_sca_device *const vsca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 				    const u8 *const sink_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	const struct v4l2_rect r = vsca->crop_rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	/* Scale each pixel from the original sink frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	/* TODO: implement scale down, only scale up is supported for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	for (i = r.top; i < r.top + r.height; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		for (j = r.left; j < r.left + r.width; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			vimc_sca_scale_pix(vsca, i, j, sink_frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static void *vimc_sca_process_frame(struct vimc_ent_device *ved,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 				    const void *sink_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	struct vimc_sca_device *vsca = container_of(ved, struct vimc_sca_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 						    ved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	/* If the stream in this node is not active, just return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	if (!vsca->src_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	vimc_sca_fill_src_frame(vsca, sink_frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	return vsca->src_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void vimc_sca_release(struct vimc_ent_device *ved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	struct vimc_sca_device *vsca =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		container_of(ved, struct vimc_sca_device, ved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	media_entity_cleanup(vsca->ved.ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	kfree(vsca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 					    const char *vcfg_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	struct vimc_sca_device *vsca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	/* Allocate the vsca struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	vsca = kzalloc(sizeof(*vsca), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	if (!vsca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	/* Initialize ved and sd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	vsca->pads[0].flags = MEDIA_PAD_FL_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	vsca->pads[1].flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	ret = vimc_ent_sd_register(&vsca->ved, &vsca->sd, v4l2_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 				   vcfg_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 				   MEDIA_ENT_F_PROC_VIDEO_SCALER, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 				   vsca->pads, &vimc_sca_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		kfree(vsca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	vsca->ved.process_frame = vimc_sca_process_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	vsca->ved.dev = vimc->mdev.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	/* Initialize the frame format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	vsca->sink_fmt = sink_fmt_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	/* Initialize the crop selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	vsca->crop_rect = crop_rect_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	return &vsca->ved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct vimc_ent_type vimc_sca_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	.add = vimc_sca_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	.release = vimc_sca_release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) };