Пример #1
0
static int uds_enum_frame_size(struct v4l2_subdev *subdev,
			       struct v4l2_subdev_pad_config *cfg,
			       struct v4l2_subdev_frame_size_enum *fse)
{
	struct vsp1_uds *uds = to_uds(subdev);
	struct v4l2_mbus_framefmt *format;

	format = vsp1_entity_get_pad_format(&uds->entity, cfg,
					    UDS_PAD_SINK, fse->which);

	if (fse->index || fse->code != format->code)
		return -EINVAL;

	if (fse->pad == UDS_PAD_SINK) {
		fse->min_width = UDS_MIN_SIZE;
		fse->max_width = UDS_MAX_SIZE;
		fse->min_height = UDS_MIN_SIZE;
		fse->max_height = UDS_MAX_SIZE;
	} else {
		uds_output_limits(format->width, &fse->min_width,
				  &fse->max_width);
		uds_output_limits(format->height, &fse->min_height,
				  &fse->max_height);
	}

	return 0;
}
Пример #2
0
static int uds_enum_mbus_code(struct v4l2_subdev *subdev,
			      struct v4l2_subdev_pad_config *cfg,
			      struct v4l2_subdev_mbus_code_enum *code)
{
	static const unsigned int codes[] = {
		MEDIA_BUS_FMT_ARGB8888_1X32,
		MEDIA_BUS_FMT_AYUV8_1X32,
	};
	struct vsp1_uds *uds = to_uds(subdev);

	if (code->pad == UDS_PAD_SINK) {
		if (code->index >= ARRAY_SIZE(codes))
			return -EINVAL;

		code->code = codes[code->index];
	} else {
		struct v4l2_mbus_framefmt *format;

		/* The UDS can't perform format conversion, the sink format is
		 * always identical to the source format.
		 */
		if (code->index)
			return -EINVAL;

		format = vsp1_entity_get_pad_format(&uds->entity, cfg,
						    UDS_PAD_SINK, code->which);
		code->code = format->code;
	}

	return 0;
}
Пример #3
0
static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
			  struct v4l2_subdev_format *fmt)
{
	struct vsp1_uds *uds = to_uds(subdev);

	fmt->format = *vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad,
						  fmt->which);

	return 0;
}
Пример #4
0
static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
{
	struct vsp1_uds *uds = to_uds(subdev);
	const struct v4l2_mbus_framefmt *output;
	const struct v4l2_mbus_framefmt *input;
	unsigned int hscale;
	unsigned int vscale;
	bool multitap;

	if (!enable)
		return 0;

	input = &uds->entity.formats[UDS_PAD_SINK];
	output = &uds->entity.formats[UDS_PAD_SOURCE];

	hscale = uds_compute_ratio(input->width, output->width);
	vscale = uds_compute_ratio(input->height, output->height);

	dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);

	/* Multi-tap scaling can't be enabled along with alpha scaling when
	 * scaling down with a factor lower than or equal to 1/2 in either
	 * direction.
	 */
	if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
		multitap = false;
	else
		multitap = true;

	vsp1_uds_write(uds, VI6_UDS_CTRL,
		       (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
		       (multitap ? VI6_UDS_CTRL_BC : 0));

	vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH,
		       (uds_passband_width(hscale)
				<< VI6_UDS_PASS_BWIDTH_H_SHIFT) |
		       (uds_passband_width(vscale)
				<< VI6_UDS_PASS_BWIDTH_V_SHIFT));

	/* Set the scaling ratios and the output size. */
	vsp1_uds_write(uds, VI6_UDS_SCALE,
		       (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
		       (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
	vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE,
		       (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
		       (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));

	return 0;
}
Пример #5
0
static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
			  struct v4l2_subdev_format *fmt)
{
	struct vsp1_uds *uds = to_uds(subdev);
	struct v4l2_mbus_framefmt *format;

	uds_try_format(uds, cfg, fmt->pad, &fmt->format, fmt->which);

	format = vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad,
					    fmt->which);
	*format = fmt->format;

	if (fmt->pad == UDS_PAD_SINK) {
		/* Propagate the format to the source pad. */
		format = vsp1_entity_get_pad_format(&uds->entity, cfg,
						    UDS_PAD_SOURCE, fmt->which);
		*format = fmt->format;

		uds_try_format(uds, cfg, UDS_PAD_SOURCE, format, fmt->which);
	}

	return 0;
}