Merge branch 'vsp1/pa-improvements' into vsp1/next
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index ac4ad26..bc419ef 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -20,6 +20,9 @@
#include <media/media-entity.h>
+/* Max Video Width / Min Partition Size = 8190/128 */
+#define VSP1_PIPE_MAX_PARTITIONS 64
+
struct vsp1_dl_list;
struct vsp1_rwpf;
@@ -77,9 +80,9 @@ 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
- * @current_partition: The partition number currently being configured
+ * @partition: The current partition for configuration to process
+ * @part_table: The pre-calculated partitions used by the pipeline
*/
struct vsp1_pipeline {
struct media_pipeline pipe;
@@ -108,10 +111,9 @@ struct vsp1_pipeline {
struct vsp1_dl_list *dl;
- unsigned int div_size;
unsigned int partitions;
struct v4l2_rect partition;
- unsigned int current_partition;
+ struct v4l2_rect part_table[VSP1_PIPE_MAX_PARTITIONS];
};
void vsp1_pipeline_reset(struct vsp1_pipeline *pipe);
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index b4e568a..42a3ed6 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -152,7 +152,8 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
fse->min_width = format->width;
fse->min_height = format->height;
if (format->width <= SRU_MAX_SIZE / 2 &&
- format->height <= SRU_MAX_SIZE / 2) {
+ format->height <= SRU_MAX_SIZE / 2 &&
+ sru->force_identity_mode == false) {
fse->max_width = format->width * 2;
fse->max_height = format->height * 2;
} else {
@@ -203,7 +204,8 @@ static void sru_try_format(struct vsp1_sru *sru,
if (fmt->width <= SRU_MAX_SIZE / 2 &&
fmt->height <= SRU_MAX_SIZE / 2 &&
- output_area > input_area * 9 / 4) {
+ output_area > input_area * 9 / 4 &&
+ sru->force_identity_mode == false) {
fmt->width = format->width * 2;
fmt->height = format->height * 2;
} else {
@@ -355,6 +357,7 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL);
sru->intensity = 1;
+ sru->force_identity_mode = false;
sru->entity.subdev.ctrl_handler = &sru->ctrls;
diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h
index 85e24145..f8652c0 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.h
+++ b/drivers/media/platform/vsp1/vsp1_sru.h
@@ -30,6 +30,7 @@ struct vsp1_sru {
struct v4l2_ctrl_handler ctrls;
unsigned int intensity;
+ bool force_identity_mode;
};
static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index a130786..7b836e1 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -33,6 +33,7 @@
#include "vsp1_entity.h"
#include "vsp1_pipe.h"
#include "vsp1_rwpf.h"
+#include "vsp1_sru.h"
#include "vsp1_uds.h"
#include "vsp1_video.h"
@@ -177,39 +178,6 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
* 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);
-}
-
/**
* vsp1_video_partition - Calculate the active partition output window
*
@@ -280,6 +248,42 @@ static struct v4l2_rect vsp1_video_partition(struct vsp1_pipeline *pipe,
return partition;
}
+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;
+ int i;
+
+ 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->partitions = 1;
+ pipe->part_table[0] = vsp1_video_partition(pipe, div_size, 0);
+ 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->partitions = DIV_ROUND_UP(format->width, div_size);
+
+ for (i = 0; i < pipe->partitions; i++)
+ pipe->part_table[i] = vsp1_video_partition(pipe, div_size, i);
+}
+
/* -----------------------------------------------------------------------------
* Pipeline Management
*/
@@ -345,12 +349,12 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
}
static void vsp1_video_pipeline_run_partition(struct vsp1_pipeline *pipe,
- struct vsp1_dl_list *dl)
+ struct vsp1_dl_list *dl,
+ unsigned int partition_number)
{
struct vsp1_entity *entity;
- pipe->partition = vsp1_video_partition(pipe, pipe->div_size,
- pipe->current_partition);
+ pipe->partition = pipe->part_table[partition_number];
list_for_each_entry(entity, &pipe->entities, list_pipe) {
if (entity->ops->configure)
@@ -363,6 +367,7 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
{
struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
struct vsp1_entity *entity;
+ unsigned int current_partition = 0;
if (!pipe->dl)
pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
@@ -379,13 +384,12 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
}
/* Run the first partition */
- pipe->current_partition = 0;
- vsp1_video_pipeline_run_partition(pipe, pipe->dl);
+ vsp1_video_pipeline_run_partition(pipe, pipe->dl, current_partition);
/* Process consecutive partitions as necessary */
- for (pipe->current_partition = 1;
- pipe->current_partition < pipe->partitions;
- pipe->current_partition++) {
+ for (current_partition = 1;
+ current_partition < pipe->partitions;
+ current_partition++) {
struct vsp1_dl_list *dl;
/*
@@ -405,7 +409,7 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
break;
}
- vsp1_video_pipeline_run_partition(pipe, dl);
+ vsp1_video_pipeline_run_partition(pipe, dl, current_partition);
vsp1_dl_list_add_chain(pipe->dl, dl);
}
@@ -453,10 +457,12 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
struct vsp1_rwpf *input,
struct vsp1_rwpf *output)
{
+ struct vsp1_device *vsp1 = output->entity.vsp1;
struct media_entity_enum ent_enum;
struct vsp1_entity *entity;
struct media_pad *pad;
bool bru_found = false;
+ bool sru_found = false;
int ret;
ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev);
@@ -503,13 +509,37 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
goto out;
}
- /* UDS can't be chained. */
+ if (entity->type == VSP1_ENTITY_SRU) {
+ struct vsp1_sru *sru = to_sru(&entity->subdev);
+
+ /*
+ * Gen3 partition algorithm restricts SRU double-scaled
+ * resolution if it is connected after a UDS entity
+ */
+ if (vsp1->info->gen == 3 && pipe->uds)
+ sru->force_identity_mode = true;
+
+ sru_found = true;
+ }
+
if (entity->type == VSP1_ENTITY_UDS) {
+ /* UDS can't be chained. */
if (pipe->uds) {
ret = -EPIPE;
goto out;
}
+ /*
+ * On Gen3 hardware using the partition algorithm, the
+ * UDS must not be connected after the SRU. Using the
+ * SRU on Gen3 will always engage the partition
+ * algorithm
+ */
+ if (vsp1->info->gen == 3 && sru_found) {
+ ret = -EPIPE;
+ goto out;
+ }
+
pipe->uds = entity;
pipe->uds_input = bru_found ? pipe->bru
: &input->entity;