public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
To: Lucas Stach <l.stach@pengutronix.de>
Cc: linux-media@vger.kernel.org, kernel@pengutronix.de,
	patchwork-lst@pengutronix.de
Subject: Re: [PATCH v3 2/9] [media] tvp5150: add userspace subdev API
Date: Mon, 14 Mar 2016 14:34:05 -0300	[thread overview]
Message-ID: <20160314143405.1e08bc99@recife.lan> (raw)
In-Reply-To: <1457969017-4088-2-git-send-email-l.stach@pengutronix.de>

Em Mon, 14 Mar 2016 16:23:30 +0100
Lucas Stach <l.stach@pengutronix.de> escreveu:

> From: Philipp Zabel <p.zabel@pengutronix.de>
> 
> This patch adds userspace V4L2 subdevice API support.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
>  drivers/media/i2c/tvp5150.c | 282 +++++++++++++++++++++++++++++++++++---------
>  1 file changed, 223 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index 6ba93a425640..67312c9d83c1 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -36,7 +36,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
>  
>  struct tvp5150 {
>  	struct v4l2_subdev sd;
> +	struct media_pad pad;

Huh? tvp5150 has already pads on it:

struct tvp5150 {
	struct v4l2_subdev sd;
#ifdef CONFIG_MEDIA_CONTROLLER
	struct media_pad pads[DEMOD_NUM_PADS];
	struct media_entity input_ent[TVP5150_INPUT_NUM];
	struct media_pad input_pad[TVP5150_INPUT_NUM];
#endif
	struct v4l2_ctrl_handler hdl;
	struct v4l2_rect rect;

	v4l2_std_id norm;	/* Current set standard */
	u32 input;
	u32 output;
	int enable;

	u16 dev_id;
	u16 rom_ver;

	enum v4l2_mbus_type mbus_type;
};

It seems that your patchset is not based on the latest version of
the driver. Please rebase it on the top of the media tree:

	https://git.linuxtv.org/media_tree.git/

Regards,
Mauro

>  	struct v4l2_ctrl_handler hdl;
> +	struct v4l2_mbus_framefmt format;
>  	struct v4l2_rect rect;
>  	struct regmap *regmap;
>  
> @@ -819,38 +821,68 @@ static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd,
>  	return 0;
>  }
>  
> -static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
> -		struct v4l2_subdev_pad_config *cfg,
> -		struct v4l2_subdev_format *format)
> +static void tvp5150_try_crop(struct tvp5150 *decoder, struct v4l2_rect *rect,
> +			       v4l2_std_id std)
>  {
> -	struct v4l2_mbus_framefmt *f;
> -	struct tvp5150 *decoder = to_tvp5150(sd);
> +	unsigned int hmax;
>  
> -	if (!format || format->pad)
> -		return -EINVAL;
> +	/* Clamp the crop rectangle boundaries to tvp5150 limits */
> +	rect->left = clamp(rect->left, 0, TVP5150_MAX_CROP_LEFT);
> +	rect->width = clamp(rect->width,
> +			    TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect->left,
> +			    TVP5150_H_MAX - rect->left);
> +	rect->top = clamp(rect->top, 0, TVP5150_MAX_CROP_TOP);
>  
> -	f = &format->format;
> +	/* tvp5150 has some special limits */
> +	rect->left = clamp(rect->left, 0, TVP5150_MAX_CROP_LEFT);
> +	rect->width = clamp_t(unsigned int, rect->width,
> +			      TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect->left,
> +			      TVP5150_H_MAX - rect->left);
> +	rect->top = clamp(rect->top, 0, TVP5150_MAX_CROP_TOP);
> +
> +	/* Calculate height based on current standard */
> +	if (std & V4L2_STD_525_60)
> +		hmax = TVP5150_V_MAX_525_60;
> +	else
> +		hmax = TVP5150_V_MAX_OTHERS;
>  
> -	tvp5150_reset(sd, 0);
> +	rect->height = clamp(rect->height,
> +			     hmax - TVP5150_MAX_CROP_TOP - rect->top,
> +			     hmax - rect->top);
> +}
>  
> -	f->width = decoder->rect.width;
> -	f->height = decoder->rect.height;
> +static void tvp5150_set_crop(struct tvp5150 *decoder, struct v4l2_rect *rect,
> +			       v4l2_std_id std)
> +{
> +	struct regmap *map = decoder->regmap;
> +	unsigned int hmax;
>  
> -	f->code = MEDIA_BUS_FMT_UYVY8_2X8;
> -	f->field = V4L2_FIELD_SEQ_TB;
> -	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
> +	if (std & V4L2_STD_525_60)
> +		hmax = TVP5150_V_MAX_525_60;
> +	else
> +		hmax = TVP5150_V_MAX_OTHERS;
>  
> -	v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width,
> -			f->height);
> -	return 0;
> +	regmap_write(map, TVP5150_VERT_BLANKING_START, rect->top);
> +	regmap_write(map, TVP5150_VERT_BLANKING_STOP,
> +		     rect->top + rect->height - hmax);
> +	regmap_write(map, TVP5150_ACT_VD_CROP_ST_MSB,
> +		     rect->left >> TVP5150_CROP_SHIFT);
> +	regmap_write(map, TVP5150_ACT_VD_CROP_ST_LSB,
> +		     rect->left | (1 << TVP5150_CROP_SHIFT));
> +	regmap_write(map, TVP5150_ACT_VD_CROP_STP_MSB,
> +		     (rect->left + rect->width - TVP5150_MAX_CROP_LEFT) >>
> +		     TVP5150_CROP_SHIFT);
> +	regmap_write(map, TVP5150_ACT_VD_CROP_STP_LSB,
> +		     rect->left + rect->width - TVP5150_MAX_CROP_LEFT);
> +
> +	decoder->rect = *rect;
>  }
>  
>  static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
>  {
> -	struct v4l2_rect rect = a->c;
>  	struct tvp5150 *decoder = to_tvp5150(sd);
> +	struct v4l2_rect rect = a->c;
>  	v4l2_std_id std;
> -	unsigned int hmax;
>  
>  	v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n",
>  		__func__, rect.left, rect.top, rect.width, rect.height);
> @@ -858,42 +890,13 @@ static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
>  	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
>  		return -EINVAL;
>  
> -	/* tvp5150 has some special limits */
> -	rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
> -	rect.width = clamp_t(unsigned int, rect.width,
> -			     TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left,
> -			     TVP5150_H_MAX - rect.left);
> -	rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP);
> -
> -	/* Calculate height based on current standard */
>  	if (decoder->norm == V4L2_STD_ALL)
>  		std = tvp5150_read_std(sd);
>  	else
>  		std = decoder->norm;
>  
> -	if (std & V4L2_STD_525_60)
> -		hmax = TVP5150_V_MAX_525_60;
> -	else
> -		hmax = TVP5150_V_MAX_OTHERS;
> -
> -	rect.height = clamp_t(unsigned int, rect.height,
> -			      hmax - TVP5150_MAX_CROP_TOP - rect.top,
> -			      hmax - rect.top);
> -
> -	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top);
> -	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP,
> -		      rect.top + rect.height - hmax);
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB,
> -		      rect.left >> TVP5150_CROP_SHIFT);
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB,
> -		      rect.left | (1 << TVP5150_CROP_SHIFT));
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB,
> -		      (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
> -		      TVP5150_CROP_SHIFT);
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB,
> -		      rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
> -
> -	decoder->rect = rect;
> +	tvp5150_try_crop(decoder, &rect, std);
> +	tvp5150_set_crop(decoder, &rect, std);
>  
>  	return 0;
>  }
> @@ -1049,6 +1052,153 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>  
>  /* ----------------------------------------------------------------------- */
>  
> +static struct v4l2_mbus_framefmt *
> +tvp5150_get_pad_format(struct tvp5150 *decoder, struct v4l2_subdev *sd,
> +			 struct v4l2_subdev_pad_config *cfg, unsigned int pad,
> +			 enum v4l2_subdev_format_whence which)
> +{
> +	switch (which) {
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +	case V4L2_SUBDEV_FORMAT_TRY:
> +		return v4l2_subdev_get_try_format(sd, cfg, pad);
> +#endif
> +	case V4L2_SUBDEV_FORMAT_ACTIVE:
> +		return &decoder->format;
> +	default:
> +		return NULL;
> +	}
> +}
> +
> +static struct v4l2_rect *
> +tvp5150_get_pad_crop(struct tvp5150 *decoder, struct v4l2_subdev *sd,
> +		       struct v4l2_subdev_pad_config *cfg, unsigned int pad,
> +		       enum v4l2_subdev_format_whence which)
> +{
> +	switch (which) {
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +	case V4L2_SUBDEV_FORMAT_TRY:
> +		return v4l2_subdev_get_try_crop(sd, cfg, pad);
> +#endif
> +	case V4L2_SUBDEV_FORMAT_ACTIVE:
> +		return &decoder->rect;
> +	default:
> +		return NULL;
> +	}
> +}
> +
> +static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
> +				   struct v4l2_subdev_pad_config *cfg,
> +				   struct v4l2_subdev_frame_size_enum *fse)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	v4l2_std_id std;
> +
> +	if (fse->index > 0 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8)
> +		return -EINVAL;
> +
> +	fse->min_width = TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT;
> +	fse->max_width = TVP5150_H_MAX;
> +
> +	/* Calculate height based on current standard */
> +	if (decoder->norm == V4L2_STD_ALL)
> +		std = tvp5150_read_std(sd);
> +	else
> +		std = decoder->norm;
> +
> +	if (std & V4L2_STD_525_60) {
> +		fse->min_height = TVP5150_V_MAX_525_60 - TVP5150_MAX_CROP_TOP;
> +		fse->max_height = TVP5150_V_MAX_525_60;
> +	} else {
> +		fse->min_height = TVP5150_V_MAX_OTHERS - TVP5150_MAX_CROP_TOP;
> +		fse->max_height = TVP5150_V_MAX_OTHERS;
> +	}
> +
> +	return 0;
> +}
> +
> +static int tvp5150_get_format(struct v4l2_subdev *sd,
> +			      struct v4l2_subdev_pad_config *cfg,
> +			      struct v4l2_subdev_format *format)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	struct v4l2_mbus_framefmt *mbus_format;
> +
> +	mbus_format = tvp5150_get_pad_format(decoder, sd, cfg,
> +					     format->pad, format->which);
> +	if (!mbus_format)
> +		return -ENOTTY;
> +
> +	format->format = *mbus_format;
> +
> +	return 0;
> +}
> +
> +static int tvp5150_set_format(struct v4l2_subdev *sd,
> +			      struct v4l2_subdev_pad_config *cfg,
> +			      struct v4l2_subdev_format *format)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	struct v4l2_mbus_framefmt *mbus_format;
> +	struct v4l2_rect *crop;
> +
> +	crop = tvp5150_get_pad_crop(decoder, sd, cfg, format->pad,
> +				    format->which);
> +	mbus_format = tvp5150_get_pad_format(decoder, sd, cfg, format->pad,
> +					     format->which);
> +	if (!crop || !mbus_format)
> +		return -ENOTTY;
> +
> +	mbus_format->width = crop->width;
> +	mbus_format->height = crop->height;
> +
> +	format->format = *mbus_format;
> +
> +	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
> +		tvp5150_reset(sd, 0);
> +
> +	v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", mbus_format->width,
> +			mbus_format->height);
> +
> +	return 0;
> +}
> +
> +static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop,
> +				struct v4l2_mbus_framefmt *format)
> +{
> +	crop->left = 0;
> +	crop->width = TVP5150_H_MAX;
> +	crop->top = 0;
> +	if (std & V4L2_STD_525_60)
> +		crop->height = TVP5150_V_MAX_525_60;
> +	else
> +		crop->height = TVP5150_V_MAX_OTHERS;
> +
> +	format->width = crop->width;
> +	format->height = crop->height;
> +	format->code = MEDIA_BUS_FMT_UYVY8_2X8;
> +	format->field = V4L2_FIELD_SEQ_TB;
> +	format->colorspace = V4L2_COLORSPACE_SMPTE170M;
> +}
> +
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +static int tvp5150_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	v4l2_std_id std;
> +
> +	if (decoder->norm == V4L2_STD_ALL)
> +		std = tvp5150_read_std(sd);
> +	else
> +		std = decoder->norm;
> +
> +	tvp5150_set_default(std, v4l2_subdev_get_try_crop(fh, 0),
> +				 v4l2_subdev_get_try_format(fh, 0));
> +	return 0;
> +}
> +#endif
> +
> +/* ----------------------------------------------------------------------- */
> +
>  static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
>  	.s_ctrl = tvp5150_s_ctrl,
>  };
> @@ -1083,8 +1233,9 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
>  
>  static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
>  	.enum_mbus_code = tvp5150_enum_mbus_code,
> -	.set_fmt = tvp5150_fill_fmt,
> -	.get_fmt = tvp5150_fill_fmt,
> +	.enum_frame_size = tvp5150_enum_frame_size,
> +	.get_fmt = tvp5150_get_format,
> +	.set_fmt = tvp5150_set_format,
>  };
>  
>  static const struct v4l2_subdev_ops tvp5150_ops = {
> @@ -1095,6 +1246,11 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
>  	.pad = &tvp5150_pad_ops,
>  };
>  
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
> +	.open = tvp5150_open,
> +};
> +#endif
>  
>  /****************************************************************************
>  			I2C Client & Driver
> @@ -1197,6 +1353,19 @@ static int tvp5150_probe(struct i2c_client *c,
>  	sd = &core->sd;
>  	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
>  
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +	sd->internal_ops = &tvp5150_internal_ops;
> +	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +
> +#endif
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	sd->entity.flags |= MEDIA_ENT_F_ATV_DECODER;
> +	core->pad.flags = MEDIA_PAD_FL_SOURCE;
> +	res = media_entity_pads_init(&sd->entity, 1, &core->pad);
> +	if (res < 0)
> +		return res;
> +#endif
> +
>  	/* 
>  	 * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID,
>  	 * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER 
> @@ -1250,14 +1419,9 @@ static int tvp5150_probe(struct i2c_client *c,
>  	v4l2_ctrl_handler_setup(&core->hdl);
>  
>  	/* Default is no cropping */
> -	core->rect.top = 0;
> -	if (tvp5150_read_std(sd) & V4L2_STD_525_60)
> -		core->rect.height = TVP5150_V_MAX_525_60;
> -	else
> -		core->rect.height = TVP5150_V_MAX_OTHERS;
> -	core->rect.left = 0;
> -	core->rect.width = TVP5150_H_MAX;
> +	tvp5150_set_default(tvp5150_read_std(sd), &core->rect, &core->format);
>  
> +	sd->dev = &c->dev;
>  	res = v4l2_async_register_subdev(sd);
>  	if (res < 0)
>  		goto err;


-- 
Thanks,
Mauro

  reply	other threads:[~2016-03-14 17:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-14 15:23 [PATCH v3 1/9] [media] tvp5150: convert register access to regmap Lucas Stach
2016-03-14 15:23 ` [PATCH v3 2/9] [media] tvp5150: add userspace subdev API Lucas Stach
2016-03-14 17:34   ` Mauro Carvalho Chehab [this message]
2016-03-14 15:23 ` [PATCH v3 3/9] [media] tvp5150: determine BT.656 or YUV 4:2:2 mode from device tree Lucas Stach
2016-03-14 18:19   ` Javier Martinez Canillas
2016-03-15 10:26     ` Lucas Stach
2016-03-14 15:23 ` [PATCH v3 4/9] [media] tvp5150: fix standard autodetection Lucas Stach
2016-03-14 15:23 ` [PATCH v3 5/9] [media] tvp5150: split reset/enable routine Lucas Stach
2016-03-14 15:23 ` [PATCH v3 6/9] [media] tvp5150: trigger autodetection on subdev open to reset cropping Lucas Stach
2016-03-14 15:23 ` [PATCH v3 7/9] [media] tvp5150: remove pin configuration from initialization tables Lucas Stach
2016-03-14 15:23 ` [PATCH v3 8/9] [media] tvp5150: Add sync lock interrupt handling Lucas Stach
2016-03-14 15:23 ` [PATCH v3 9/9] [media] tvp5150: disable output while signal not locked Lucas Stach

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160314143405.1e08bc99@recife.lan \
    --to=mchehab@osg.samsung.com \
    --cc=kernel@pengutronix.de \
    --cc=l.stach@pengutronix.de \
    --cc=linux-media@vger.kernel.org \
    --cc=patchwork-lst@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox