Commit e575095d authored by Laurent Pinchart's avatar Laurent Pinchart

media: renesas: vsp1: Move partition calculation to vsp1_pipe.c

The partition calculation code, located in vsp1_video.c, is not specific
to video pipelines. To prepare for its usage in DRM pipelines, move it
to vsp1_pipe.c.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: default avatarJacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
parent 177bfb68
......@@ -444,6 +444,10 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
vsp1_uds_set_alpha(pipe->uds, dlb, alpha);
}
/* -----------------------------------------------------------------------------
* VSP1 Partition Algorithm support
*/
/*
* Propagate the partition calculations through the pipeline
*
......@@ -452,7 +456,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
* source. Each entity must produce the partition required for the previous
* entity in the pipeline.
*/
void vsp1_pipeline_propagate_partition(struct vsp1_pipeline *pipe,
static void vsp1_pipeline_propagate_partition(struct vsp1_pipeline *pipe,
struct vsp1_partition *partition,
unsigned int index,
struct vsp1_partition_window *window)
......@@ -466,3 +470,76 @@ void vsp1_pipeline_propagate_partition(struct vsp1_pipeline *pipe,
}
}
/*
* vsp1_pipeline_calculate_partition - Calculate pipeline configuration for a
* partition
*
* @pipe: the pipeline
* @partition: partition that will hold the calculated values
* @div_size: pre-determined maximum partition division size
* @index: partition index
*/
void vsp1_pipeline_calculate_partition(struct vsp1_pipeline *pipe,
struct vsp1_partition *partition,
unsigned int div_size,
unsigned int index)
{
const struct v4l2_mbus_framefmt *format;
struct vsp1_partition_window window;
unsigned int modulus;
/*
* Partitions are computed on the size before rotation, use the format
* at the WPF sink.
*/
format = v4l2_subdev_state_get_format(pipe->output->entity.state,
RWPF_PAD_SINK);
/* A single partition simply processes the output size in full. */
if (pipe->partitions <= 1) {
window.left = 0;
window.width = format->width;
vsp1_pipeline_propagate_partition(pipe, partition, index,
&window);
return;
}
/* Initialise the partition with sane starting conditions. */
window.left = index * div_size;
window.width = div_size;
modulus = format->width % div_size;
/*
* We need to prevent the last partition from being smaller than the
* *minimum* width of the hardware capabilities.
*
* If the modulus is less than half of the partition size,
* the penultimate partition is reduced to half, which is added
* to the final partition: |1234|1234|1234|12|341|
* to prevent this: |1234|1234|1234|1234|1|.
*/
if (modulus) {
/*
* pipe->partitions is 1 based, whilst index is a 0 based index.
* Normalise this locally.
*/
unsigned int partitions = pipe->partitions - 1;
if (modulus < div_size / 2) {
if (index == partitions - 1) {
/* Halve the penultimate partition. */
window.width = div_size / 2;
} else if (index == partitions) {
/* Increase the final partition. */
window.width = (div_size / 2) + modulus;
window.left -= div_size / 2;
}
} else if (index == partitions) {
window.width = modulus;
}
}
vsp1_pipeline_propagate_partition(pipe, partition, index, &window);
}
......@@ -166,10 +166,10 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
struct vsp1_dl_body *dlb,
unsigned int alpha);
void vsp1_pipeline_propagate_partition(struct vsp1_pipeline *pipe,
void vsp1_pipeline_calculate_partition(struct vsp1_pipeline *pipe,
struct vsp1_partition *partition,
unsigned int index,
struct vsp1_partition_window *window);
unsigned int div_size,
unsigned int index);
const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
u32 fourcc);
......
......@@ -178,129 +178,6 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
return 0;
}
/* -----------------------------------------------------------------------------
* VSP1 Partition Algorithm support
*/
/**
* vsp1_video_calculate_partition - Calculate the active partition output window
*
* @pipe: the pipeline
* @partition: partition that will hold the calculated values
* @div_size: pre-determined maximum partition division size
* @index: partition index
*/
static void vsp1_video_calculate_partition(struct vsp1_pipeline *pipe,
struct vsp1_partition *partition,
unsigned int div_size,
unsigned int index)
{
const struct v4l2_mbus_framefmt *format;
struct vsp1_partition_window window;
unsigned int modulus;
/*
* Partitions are computed on the size before rotation, use the format
* at the WPF sink.
*/
format = v4l2_subdev_state_get_format(pipe->output->entity.state,
RWPF_PAD_SINK);
/* A single partition simply processes the output size in full. */
if (pipe->partitions <= 1) {
window.left = 0;
window.width = format->width;
vsp1_pipeline_propagate_partition(pipe, partition, index,
&window);
return;
}
/* Initialise the partition with sane starting conditions. */
window.left = index * div_size;
window.width = div_size;
modulus = format->width % div_size;
/*
* We need to prevent the last partition from being smaller than the
* *minimum* width of the hardware capabilities.
*
* If the modulus is less than half of the partition size,
* the penultimate partition is reduced to half, which is added
* to the final partition: |1234|1234|1234|12|341|
* to prevent this: |1234|1234|1234|1234|1|.
*/
if (modulus) {
/*
* pipe->partitions is 1 based, whilst index is a 0 based index.
* Normalise this locally.
*/
unsigned int partitions = pipe->partitions - 1;
if (modulus < div_size / 2) {
if (index == partitions - 1) {
/* Halve the penultimate partition. */
window.width = div_size / 2;
} else if (index == partitions) {
/* Increase the final partition. */
window.width = (div_size / 2) + modulus;
window.left -= div_size / 2;
}
} else if (index == partitions) {
window.width = modulus;
}
}
vsp1_pipeline_propagate_partition(pipe, partition, index, &window);
}
static int 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;
unsigned int i;
/*
* Partitions are computed on the size before rotation, use the format
* at the WPF sink.
*/
format = v4l2_subdev_state_get_format(pipe->output->entity.state,
RWPF_PAD_SINK);
div_size = format->width;
/*
* Only Gen3+ hardware requires image partitioning, Gen2 will operate
* with a single partition that covers the whole output.
*/
if (vsp1->info->gen >= 3) {
list_for_each_entry(entity, &pipe->entities, list_pipe) {
unsigned int entity_max;
if (!entity->ops->max_width)
continue;
entity_max = entity->ops->max_width(entity, pipe);
if (entity_max)
div_size = min(div_size, entity_max);
}
}
pipe->partitions = DIV_ROUND_UP(format->width, div_size);
pipe->part_table = kcalloc(pipe->partitions, sizeof(*pipe->part_table),
GFP_KERNEL);
if (!pipe->part_table)
return -ENOMEM;
for (i = 0; i < pipe->partitions; ++i)
vsp1_video_calculate_partition(pipe, &pipe->part_table[i],
div_size, i);
return 0;
}
/* -----------------------------------------------------------------------------
* Pipeline Management
*/
......@@ -788,6 +665,52 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&pipe->irqlock, flags);
}
static int 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;
unsigned int i;
/*
* Partitions are computed on the size before rotation, use the format
* at the WPF sink.
*/
format = v4l2_subdev_state_get_format(pipe->output->entity.state,
RWPF_PAD_SINK);
div_size = format->width;
/*
* Only Gen3+ hardware requires image partitioning, Gen2 will operate
* with a single partition that covers the whole output.
*/
if (vsp1->info->gen >= 3) {
list_for_each_entry(entity, &pipe->entities, list_pipe) {
unsigned int entity_max;
if (!entity->ops->max_width)
continue;
entity_max = entity->ops->max_width(entity, pipe);
if (entity_max)
div_size = min(div_size, entity_max);
}
}
pipe->partitions = DIV_ROUND_UP(format->width, div_size);
pipe->part_table = kcalloc(pipe->partitions, sizeof(*pipe->part_table),
GFP_KERNEL);
if (!pipe->part_table)
return -ENOMEM;
for (i = 0; i < pipe->partitions; ++i)
vsp1_pipeline_calculate_partition(pipe, &pipe->part_table[i],
div_size, i);
return 0;
}
static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
{
struct vsp1_entity *entity;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment