mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 17:51:41 -04:00
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: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
This commit is contained in:
@@ -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,10 +456,10 @@ 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,
|
||||
struct vsp1_partition *partition,
|
||||
unsigned int index,
|
||||
struct vsp1_partition_window *window)
|
||||
static void vsp1_pipeline_propagate_partition(struct vsp1_pipeline *pipe,
|
||||
struct vsp1_partition *partition,
|
||||
unsigned int index,
|
||||
struct vsp1_partition_window *window)
|
||||
{
|
||||
struct vsp1_entity *entity;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user