diff options
| author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2024-04-25 02:57:39 +0300 | 
|---|---|---|
| committer | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2024-06-26 17:39:34 +0300 | 
| commit | cf2552d87ac0e50f98c1e18d233a74ca58af819f (patch) | |
| tree | 83bbdbb2fe4335e370f9b91626b907a23f58ccaf /drivers/media/test-drivers/vimc/vimc-sensor.c | |
| parent | b3f73b21887ecda4c03a61085c7290ce585016d0 (diff) | |
| download | linux-cf2552d87ac0e50f98c1e18d233a74ca58af819f.tar.xz | |
media: vimc: sensor: Use subdev active state
Store the active formats and crop rectangle in the subdevice active
state. This simplifies implementation of the format and selection
accessors, and allows using the v4l2_subdev_get_fmt() helper to
implement the .get_fmt() operation.
The active configuration that is used in the .process_frame() handler is
still stored in the vimc_sensor_device structure. The driver could
instead access the active state in the .process_frame() handler, but the
required locking could interfere with the real time constraints of the
frame processing. This data would be stored in registers in the
.s_stream() handler for real hardware, storing it in dedicated storage
thus mimics a real driver. To differentiate them from the rest of the
device private data, move the corresponding fields to a sub-structure of
vimc_sensor_device named hw.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Diffstat (limited to 'drivers/media/test-drivers/vimc/vimc-sensor.c')
| -rw-r--r-- | drivers/media/test-drivers/vimc/vimc-sensor.c | 108 | 
1 files changed, 50 insertions, 58 deletions
diff --git a/drivers/media/test-drivers/vimc/vimc-sensor.c b/drivers/media/test-drivers/vimc/vimc-sensor.c index 9eb24c4791bf..027767777763 100644 --- a/drivers/media/test-drivers/vimc/vimc-sensor.c +++ b/drivers/media/test-drivers/vimc/vimc-sensor.c @@ -24,13 +24,20 @@ struct vimc_sensor_device {  	struct vimc_ent_device ved;  	struct v4l2_subdev sd;  	struct tpg_data tpg; -	u8 *frame; -	enum vimc_sensor_osd_mode osd_value; -	u64 start_stream_ts; -	/* The active format */ -	struct v4l2_mbus_framefmt mbus_format;  	struct v4l2_ctrl_handler hdl;  	struct media_pad pad; + +	u8 *frame; + +	/* +	 * Virtual "hardware" configuration, filled when the stream starts or +	 * when controls are set. +	 */ +	struct { +		struct v4l2_area size; +		enum vimc_sensor_osd_mode osd_value; +		u64 start_stream_ts; +	} hw;  };  static const struct v4l2_mbus_framefmt fmt_default = { @@ -88,36 +95,22 @@ static int vimc_sensor_enum_frame_size(struct v4l2_subdev *sd,  	return 0;  } -static int vimc_sensor_get_fmt(struct v4l2_subdev *sd, -			       struct v4l2_subdev_state *sd_state, -			       struct v4l2_subdev_format *fmt) +static void vimc_sensor_tpg_s_format(struct vimc_sensor_device *vsensor, +				     const struct v4l2_mbus_framefmt *format)  { -	struct vimc_sensor_device *vsensor = -				container_of(sd, struct vimc_sensor_device, sd); - -	fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ? -		      *v4l2_subdev_state_get_format(sd_state, fmt->pad) : -		      vsensor->mbus_format; +	const struct vimc_pix_map *vpix = vimc_pix_map_by_code(format->code); -	return 0; -} - -static void vimc_sensor_tpg_s_format(struct vimc_sensor_device *vsensor) -{ -	const struct vimc_pix_map *vpix = -				vimc_pix_map_by_code(vsensor->mbus_format.code); - -	tpg_reset_source(&vsensor->tpg, vsensor->mbus_format.width, -			 vsensor->mbus_format.height, vsensor->mbus_format.field); -	tpg_s_bytesperline(&vsensor->tpg, 0, vsensor->mbus_format.width * vpix->bpp); -	tpg_s_buf_height(&vsensor->tpg, vsensor->mbus_format.height); +	tpg_reset_source(&vsensor->tpg, format->width, format->height, +			 format->field); +	tpg_s_bytesperline(&vsensor->tpg, 0, format->width * vpix->bpp); +	tpg_s_buf_height(&vsensor->tpg, format->height);  	tpg_s_fourcc(&vsensor->tpg, vpix->pixelformat);  	/* TODO: add support for V4L2_FIELD_ALTERNATE */ -	tpg_s_field(&vsensor->tpg, vsensor->mbus_format.field, false); -	tpg_s_colorspace(&vsensor->tpg, vsensor->mbus_format.colorspace); -	tpg_s_ycbcr_enc(&vsensor->tpg, vsensor->mbus_format.ycbcr_enc); -	tpg_s_quantization(&vsensor->tpg, vsensor->mbus_format.quantization); -	tpg_s_xfer_func(&vsensor->tpg, vsensor->mbus_format.xfer_func); +	tpg_s_field(&vsensor->tpg, format->field, false); +	tpg_s_colorspace(&vsensor->tpg, format->colorspace); +	tpg_s_ycbcr_enc(&vsensor->tpg, format->ycbcr_enc); +	tpg_s_quantization(&vsensor->tpg, format->quantization); +	tpg_s_xfer_func(&vsensor->tpg, format->xfer_func);  }  static void vimc_sensor_adjust_fmt(struct v4l2_mbus_framefmt *fmt) @@ -148,15 +141,11 @@ static int vimc_sensor_set_fmt(struct v4l2_subdev *sd,  	struct vimc_sensor_device *vsensor = v4l2_get_subdevdata(sd);  	struct v4l2_mbus_framefmt *mf; -	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { -		/* Do not change the format while stream is on */ -		if (vsensor->frame) -			return -EBUSY; +	/* Do not change the format while stream is on */ +	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && vsensor->frame) +		return -EBUSY; -		mf = &vsensor->mbus_format; -	} else { -		mf = v4l2_subdev_state_get_format(sd_state, fmt->pad); -	} +	mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);  	/* Set the new format */  	vimc_sensor_adjust_fmt(&fmt->format); @@ -181,7 +170,7 @@ static int vimc_sensor_set_fmt(struct v4l2_subdev *sd,  static const struct v4l2_subdev_pad_ops vimc_sensor_pad_ops = {  	.enum_mbus_code		= vimc_sensor_enum_mbus_code,  	.enum_frame_size	= vimc_sensor_enum_frame_size, -	.get_fmt		= vimc_sensor_get_fmt, +	.get_fmt		= v4l2_subdev_get_fmt,  	.set_fmt		= vimc_sensor_set_fmt,  }; @@ -198,7 +187,7 @@ static void *vimc_sensor_process_frame(struct vimc_ent_device *ved,  	tpg_fill_plane_buffer(&vsensor->tpg, 0, 0, vsensor->frame);  	tpg_calc_text_basep(&vsensor->tpg, basep, 0, vsensor->frame); -	switch (vsensor->osd_value) { +	switch (vsensor->hw.osd_value) {  	case VIMC_SENSOR_OSD_SHOW_ALL: {  		const char *order = tpg_g_color_order(&vsensor->tpg); @@ -212,15 +201,14 @@ static void *vimc_sensor_process_frame(struct vimc_ent_device *ved,  			 vsensor->tpg.hue);  		tpg_gen_text(&vsensor->tpg, basep, line++ * line_height, 16, str);  		snprintf(str, sizeof(str), "sensor size: %dx%d", -			 vsensor->mbus_format.width, -			 vsensor->mbus_format.height); +			 vsensor->hw.size.width, vsensor->hw.size.height);  		tpg_gen_text(&vsensor->tpg, basep, line++ * line_height, 16, str);  		fallthrough;  	}  	case VIMC_SENSOR_OSD_SHOW_COUNTERS: {  		unsigned int ms; -		ms = div_u64(ktime_get_ns() - vsensor->start_stream_ts, 1000000); +		ms = div_u64(ktime_get_ns() - vsensor->hw.start_stream_ts, 1000000);  		snprintf(str, sizeof(str), "%02d:%02d:%02d:%03d",  			 (ms / (60 * 60 * 1000)) % 24,  			 (ms / (60 * 1000)) % 60, @@ -243,15 +231,25 @@ static int vimc_sensor_s_stream(struct v4l2_subdev *sd, int enable)  				container_of(sd, struct vimc_sensor_device, sd);  	if (enable) { +		const struct v4l2_mbus_framefmt *format; +		struct v4l2_subdev_state *state;  		const struct vimc_pix_map *vpix;  		unsigned int frame_size; -		vsensor->start_stream_ts = ktime_get_ns(); +		state = v4l2_subdev_lock_and_get_active_state(sd); +		format = v4l2_subdev_state_get_format(state, 0); -		/* Calculate the frame size */ -		vpix = vimc_pix_map_by_code(vsensor->mbus_format.code); -		frame_size = vsensor->mbus_format.width * vpix->bpp * -			     vsensor->mbus_format.height; +		/* Configure the test pattern generator. */ +		vimc_sensor_tpg_s_format(vsensor, format); + +		/* Calculate the frame size. */ +		vpix = vimc_pix_map_by_code(format->code); +		frame_size = format->width * vpix->bpp * format->height; + +		vsensor->hw.size.width = format->width; +		vsensor->hw.size.height = format->height; + +		v4l2_subdev_unlock_state(state);  		/*  		 * Allocate the frame buffer. Use vmalloc to be able to @@ -261,9 +259,7 @@ static int vimc_sensor_s_stream(struct v4l2_subdev *sd, int enable)  		if (!vsensor->frame)  			return -ENOMEM; -		/* configure the test pattern generator */ -		vimc_sensor_tpg_s_format(vsensor); - +		vsensor->hw.start_stream_ts = ktime_get_ns();  	} else {  		vfree(vsensor->frame); @@ -321,7 +317,7 @@ static int vimc_sensor_s_ctrl(struct v4l2_ctrl *ctrl)  		tpg_s_saturation(&vsensor->tpg, ctrl->val);  		break;  	case VIMC_CID_OSD_TEXT_MODE: -		vsensor->osd_value = ctrl->val; +		vsensor->hw.osd_value = ctrl->val;  		break;  	default:  		return -EINVAL; @@ -414,8 +410,7 @@ static struct vimc_ent_device *vimc_sensor_add(struct vimc_device *vimc,  	}  	/* Initialize the test pattern generator */ -	tpg_init(&vsensor->tpg, vsensor->mbus_format.width, -		 vsensor->mbus_format.height); +	tpg_init(&vsensor->tpg, fmt_default.width, fmt_default.height);  	ret = tpg_alloc(&vsensor->tpg, VIMC_FRAME_MAX_WIDTH);  	if (ret)  		goto err_free_hdl; @@ -432,9 +427,6 @@ static struct vimc_ent_device *vimc_sensor_add(struct vimc_device *vimc,  	vsensor->ved.process_frame = vimc_sensor_process_frame;  	vsensor->ved.dev = vimc->mdev.dev; -	/* Initialize the frame format */ -	vsensor->mbus_format = fmt_default; -  	return &vsensor->ved;  err_free_tpg:  | 
