[media] v4l: vsp1: Determine partition requirements for scaled images

The partition algorithm needs to determine the capabilities of each
entity in the pipeline to identify the correct maximum partition width.

Extend the vsp1 entity operations to provide a max_width operation and
use this call to calculate the number of partitions that will be
processed by the algorithm.

Gen 2 hardware does not require multiple partitioning, and as such
will always return a single partition.

Signed-off-by: Kieran Bingham <kieran+renesas@bingham.xyz>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Kieran Bingham 2016-07-12 10:06:34 -03:00 committed by Mauro Carvalho Chehab
parent 76e48896c0
commit df32c92451
5 changed files with 92 additions and 0 deletions

View File

@ -77,11 +77,14 @@ struct vsp1_route {
* @destroy: Destroy the entity.
* @configure: Setup the hardware based on the entity state (pipeline, formats,
* selection rectangles, ...)
* @max_width: Return the max supported width of data that the entity can
* process in a single operation.
*/
struct vsp1_entity_operations {
void (*destroy)(struct vsp1_entity *);
void (*configure)(struct vsp1_entity *, struct vsp1_pipeline *,
struct vsp1_dl_list *, enum vsp1_entity_params);
unsigned int (*max_width)(struct vsp1_entity *, struct vsp1_pipeline *);
};
struct vsp1_entity {

View File

@ -77,6 +77,8 @@ enum vsp1_pipeline_state {
* @uds_input: entity at the input of the UDS, if the UDS is present
* @entities: list of entities in the pipeline
* @dl: display list associated with the pipeline
* @div_size: The maximum allowed partition size for the pipeline
* @partitions: The number of partitions used to process one frame
*/
struct vsp1_pipeline {
struct media_pipeline pipe;
@ -104,6 +106,9 @@ struct vsp1_pipeline {
struct list_head entities;
struct vsp1_dl_list *dl;
unsigned int div_size;
unsigned int partitions;
};
void vsp1_pipeline_reset(struct vsp1_pipeline *pipe);

View File

@ -306,8 +306,27 @@ static void sru_configure(struct vsp1_entity *entity,
vsp1_sru_write(sru, dl, VI6_SRU_CTRL2, param->ctrl2);
}
static unsigned int sru_max_width(struct vsp1_entity *entity,
struct vsp1_pipeline *pipe)
{
struct vsp1_sru *sru = to_sru(&entity->subdev);
struct v4l2_mbus_framefmt *input;
struct v4l2_mbus_framefmt *output;
input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
SRU_PAD_SINK);
output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
SRU_PAD_SOURCE);
if (input->width != output->width)
return 512;
else
return 256;
}
static const struct vsp1_entity_operations sru_entity_ops = {
.configure = sru_configure,
.max_width = sru_max_width,
};
/* -----------------------------------------------------------------------------

View File

@ -311,8 +311,33 @@ static void uds_configure(struct vsp1_entity *entity,
(output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
}
static unsigned int uds_max_width(struct vsp1_entity *entity,
struct vsp1_pipeline *pipe)
{
struct vsp1_uds *uds = to_uds(&entity->subdev);
const struct v4l2_mbus_framefmt *output;
const struct v4l2_mbus_framefmt *input;
unsigned int hscale;
input = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
UDS_PAD_SINK);
output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
UDS_PAD_SOURCE);
hscale = output->width / input->width;
if (hscale <= 2)
return 256;
else if (hscale <= 4)
return 512;
else if (hscale <= 8)
return 1024;
else
return 2048;
}
static const struct vsp1_entity_operations uds_entity_ops = {
.configure = uds_configure,
.max_width = uds_max_width,
};
/* -----------------------------------------------------------------------------

View File

@ -168,6 +168,43 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
return 0;
}
/* -----------------------------------------------------------------------------
* VSP1 Partition Algorithm support
*/
static void vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe)
{
struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
const struct v4l2_mbus_framefmt *format;
struct vsp1_entity *entity;
unsigned int div_size;
format = vsp1_entity_get_pad_format(&pipe->output->entity,
pipe->output->entity.config,
RWPF_PAD_SOURCE);
div_size = format->width;
/* Gen2 hardware doesn't require image partitioning. */
if (vsp1->info->gen == 2) {
pipe->div_size = div_size;
pipe->partitions = 1;
return;
}
list_for_each_entry(entity, &pipe->entities, list_pipe) {
unsigned int entity_max = VSP1_VIDEO_MAX_WIDTH;
if (entity->ops->max_width) {
entity_max = entity->ops->max_width(entity, pipe);
if (entity_max)
div_size = min(div_size, entity_max);
}
}
pipe->div_size = div_size;
pipe->partitions = DIV_ROUND_UP(format->width, div_size);
}
/* -----------------------------------------------------------------------------
* Pipeline Management
*/
@ -594,6 +631,9 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
{
struct vsp1_entity *entity;
/* Determine this pipelines sizes for image partitioning support. */
vsp1_video_pipeline_setup_partitions(pipe);
/* Prepare the display list. */
pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
if (!pipe->dl)