@@ -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;