Re: [PATCH] media: vimc: Implement get/set selection

2019-09-26 Thread Hans Verkuil
On 9/25/19 8:15 PM, Helen Koike wrote:
> +Hans +Shuah
> 
> Hi Guilherme and Danilo,
> 
> Thank you for the patch, please see my comments below.
> 
> On 9/9/19 1:08 AM, Guilherme Alcarde Gallo wrote:
>> Add support for the scaler subdevice to respond VIDIOC_G_SELECTION and
>> VIDIOC_S_SELECTION ioctls with the following targets:
>> V4L2_SEL_TGT_COMPOSE_BOUNDS and V4L2_SEL_TGT_CROP.
>>
>> * Added new const struct crop_rect_default to initialize subdev scaler
>>   properly.
>> * Make changes in sink pad format reflect the crop rectangle. E.g.
>>   changing the frame format to a smaller size one can make the former
>>   crop rectangle selects a non existing frame area. To solve this
>>   situation the crop rectangle is clamped to the frame boundaries.
>> * Clamp crop rectangle respecting the sink bounds during set_selection
>>   ioctl.
>>
>> Signed-off-by: Guilherme Alcarde Gallo 
>> Co-developed-by: Danilo Figueiredo Rocha 
>> Signed-off-by: Danilo Figueiredo Rocha 
>>
>> ---
>>
>> This patch is based on the monolithic vimc driver from the patchset
>> named "Collapse vimc into single monolithic driver"
>> https://patchwork.kernel.org/patch/11136201/
>>
>> ---
>>
>>  drivers/media/platform/vimc/vimc-scaler.c | 148 +++---
>>  1 file changed, 133 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/media/platform/vimc/vimc-scaler.c 
>> b/drivers/media/platform/vimc/vimc-scaler.c
>> index a5a0855ad9cd..b50d11e76a2b 100644
>> --- a/drivers/media/platform/vimc/vimc-scaler.c
>> +++ b/drivers/media/platform/vimc/vimc-scaler.c
>> @@ -18,6 +18,9 @@ MODULE_PARM_DESC(sca_mult, " the image size multiplier");
>>  
>>  #define MAX_ZOOM8
>>  
>> +#define VIMC_SCA_FMT_WIDTH_DEFAULT  640
>> +#define VIMC_SCA_FMT_HEIGHT_DEFAULT 480
>> +
>>  struct vimc_sca_device {
>>  struct vimc_ent_device ved;
>>  struct v4l2_subdev sd;
>> @@ -26,6 +29,7 @@ struct vimc_sca_device {
>>   * with the width and hight multiplied by mult
>>   */
>>  struct v4l2_mbus_framefmt sink_fmt;
>> +struct v4l2_rect crop_rect;
>>  /* Values calculated when the stream starts */
>>  u8 *src_frame;
>>  unsigned int src_line_size;
>> @@ -33,22 +37,33 @@ struct vimc_sca_device {
>>  };
>>  
>>  static const struct v4l2_mbus_framefmt sink_fmt_default = {
>> -.width = 640,
>> -.height = 480,
>> +.width = VIMC_SCA_FMT_WIDTH_DEFAULT,
>> +.height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
>>  .code = MEDIA_BUS_FMT_RGB888_1X24,
>>  .field = V4L2_FIELD_NONE,
>>  .colorspace = V4L2_COLORSPACE_DEFAULT,
>>  };
>>  
>> +static const struct v4l2_rect crop_rect_default = {
>> +.width = VIMC_SCA_FMT_WIDTH_DEFAULT,
>> +.height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
>> +.top = 0,
>> +.left = 0,
>> +};
>> +
>>  static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
>>   struct v4l2_subdev_pad_config *cfg)
>>  {
>>  struct v4l2_mbus_framefmt *mf;
>> +struct v4l2_rect *r;
>>  unsigned int i;
>>  
>>  mf = v4l2_subdev_get_try_format(sd, cfg, 0);
>>  *mf = sink_fmt_default;
>>  
>> +r = v4l2_subdev_get_try_crop(sd, cfg, 0);
>> +*r = crop_rect_default;
>> +
>>  for (i = 1; i < sd->entity.num_pads; i++) {
>>  mf = v4l2_subdev_get_try_format(sd, cfg, i);
>>  *mf = sink_fmt_default;
>> @@ -107,16 +122,21 @@ static int vimc_sca_get_fmt(struct v4l2_subdev *sd,
>>  struct v4l2_subdev_format *format)
>>  {
>>  struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
>> +struct v4l2_rect *crop_rect;
>>  
>>  /* Get the current sink format */
>> -format->format = (format->which == V4L2_SUBDEV_FORMAT_TRY) ?
>> - *v4l2_subdev_get_try_format(sd, cfg, 0) :
>> - vsca->sink_fmt;
>> +if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
>> +format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
>> +crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
>> +} else {
>> +format->format = vsca->sink_fmt;
>> +crop_rect = &vsca->crop_rect;
>> +}
>>  
>>  /* Scale the frame size for the source pad */
>>  if (VIMC_IS_SRC(format->pad)) {
>> -format->format.width = vsca->sink_fmt.width * sca_mult;
>> -format->format.height = vsca->sink_fmt.height * sca_mult;
>> +format->format.width = crop_rect->width * sca_mult;
>> +format->format.height = crop_rect->height * sca_mult;
>>  }
>>  
>>  return 0;
>> @@ -148,6 +168,7 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
>>  {
>>  struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
>>  struct v4l2_mbus_framefmt *sink_fmt;
>> +struct v4l2_rect *crop_rect;
>>  
>>  if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
>>  /* Do not change the format while stream is on */
>> @@ -155,8 +176,10 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
>>  return -EBUSY;
>>  

Re: [PATCH] media: vimc: Implement get/set selection

2019-09-25 Thread Helen Koike
+Hans +Shuah

Hi Guilherme and Danilo,

Thank you for the patch, please see my comments below.

On 9/9/19 1:08 AM, Guilherme Alcarde Gallo wrote:
> Add support for the scaler subdevice to respond VIDIOC_G_SELECTION and
> VIDIOC_S_SELECTION ioctls with the following targets:
> V4L2_SEL_TGT_COMPOSE_BOUNDS and V4L2_SEL_TGT_CROP.
> 
> * Added new const struct crop_rect_default to initialize subdev scaler
>   properly.
> * Make changes in sink pad format reflect the crop rectangle. E.g.
>   changing the frame format to a smaller size one can make the former
>   crop rectangle selects a non existing frame area. To solve this
>   situation the crop rectangle is clamped to the frame boundaries.
> * Clamp crop rectangle respecting the sink bounds during set_selection
>   ioctl.
> 
> Signed-off-by: Guilherme Alcarde Gallo 
> Co-developed-by: Danilo Figueiredo Rocha 
> Signed-off-by: Danilo Figueiredo Rocha 
> 
> ---
> 
> This patch is based on the monolithic vimc driver from the patchset
> named "Collapse vimc into single monolithic driver"
> https://patchwork.kernel.org/patch/11136201/
> 
> ---
> 
>  drivers/media/platform/vimc/vimc-scaler.c | 148 +++---
>  1 file changed, 133 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/media/platform/vimc/vimc-scaler.c 
> b/drivers/media/platform/vimc/vimc-scaler.c
> index a5a0855ad9cd..b50d11e76a2b 100644
> --- a/drivers/media/platform/vimc/vimc-scaler.c
> +++ b/drivers/media/platform/vimc/vimc-scaler.c
> @@ -18,6 +18,9 @@ MODULE_PARM_DESC(sca_mult, " the image size multiplier");
>  
>  #define MAX_ZOOM 8
>  
> +#define VIMC_SCA_FMT_WIDTH_DEFAULT   640
> +#define VIMC_SCA_FMT_HEIGHT_DEFAULT  480
> +
>  struct vimc_sca_device {
>   struct vimc_ent_device ved;
>   struct v4l2_subdev sd;
> @@ -26,6 +29,7 @@ struct vimc_sca_device {
>* with the width and hight multiplied by mult
>*/
>   struct v4l2_mbus_framefmt sink_fmt;
> + struct v4l2_rect crop_rect;
>   /* Values calculated when the stream starts */
>   u8 *src_frame;
>   unsigned int src_line_size;
> @@ -33,22 +37,33 @@ struct vimc_sca_device {
>  };
>  
>  static const struct v4l2_mbus_framefmt sink_fmt_default = {
> - .width = 640,
> - .height = 480,
> + .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
> + .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
>   .code = MEDIA_BUS_FMT_RGB888_1X24,
>   .field = V4L2_FIELD_NONE,
>   .colorspace = V4L2_COLORSPACE_DEFAULT,
>  };
>  
> +static const struct v4l2_rect crop_rect_default = {
> + .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
> + .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
> + .top = 0,
> + .left = 0,
> +};
> +
>  static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
>struct v4l2_subdev_pad_config *cfg)
>  {
>   struct v4l2_mbus_framefmt *mf;
> + struct v4l2_rect *r;
>   unsigned int i;
>  
>   mf = v4l2_subdev_get_try_format(sd, cfg, 0);
>   *mf = sink_fmt_default;
>  
> + r = v4l2_subdev_get_try_crop(sd, cfg, 0);
> + *r = crop_rect_default;
> +
>   for (i = 1; i < sd->entity.num_pads; i++) {
>   mf = v4l2_subdev_get_try_format(sd, cfg, i);
>   *mf = sink_fmt_default;
> @@ -107,16 +122,21 @@ static int vimc_sca_get_fmt(struct v4l2_subdev *sd,
>   struct v4l2_subdev_format *format)
>  {
>   struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
> + struct v4l2_rect *crop_rect;
>  
>   /* Get the current sink format */
> - format->format = (format->which == V4L2_SUBDEV_FORMAT_TRY) ?
> -  *v4l2_subdev_get_try_format(sd, cfg, 0) :
> -  vsca->sink_fmt;
> + if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
> + format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
> + crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
> + } else {
> + format->format = vsca->sink_fmt;
> + crop_rect = &vsca->crop_rect;
> + }
>  
>   /* Scale the frame size for the source pad */
>   if (VIMC_IS_SRC(format->pad)) {
> - format->format.width = vsca->sink_fmt.width * sca_mult;
> - format->format.height = vsca->sink_fmt.height * sca_mult;
> + format->format.width = crop_rect->width * sca_mult;
> + format->format.height = crop_rect->height * sca_mult;
>   }
>  
>   return 0;
> @@ -148,6 +168,7 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
>  {
>   struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
>   struct v4l2_mbus_framefmt *sink_fmt;
> + struct v4l2_rect *crop_rect;
>  
>   if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
>   /* Do not change the format while stream is on */
> @@ -155,8 +176,10 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
>   return -EBUSY;
>  
>   sink_fmt = &vsca->sink_fmt;
> + crop_rect = &vsca->crop_rect;
>   } else {
>