aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKieran Bingham <kieran.bingham+renesas@ideasonboard.com>2018-05-18 16:42:01 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-05-25 19:03:16 -0400
commit46ce3639a579c29dc3166a9a66522f72f11f560c (patch)
tree13bb07c31eb5edde959931cf7ef23d5b2f6bd5bc
parent2d9445db0ee9d8695ab3dadb614829b70e43b61f (diff)
media: vsp1: Refactor display list configure operations
The entities provide a single .configure operation which configures the object into the target display list, based on the vsp1_entity_params selection. Split the configure function into three parts, '.configure_stream()', '.configure_frame()', and '.configure_partition()' to facilitate splitting the configuration of each parameter class into separate display list bodies. [laurent.pinchart+renesas@ideasonboard.com: Blank line reformatting, remote unneeded local variable initialization] Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--drivers/media/platform/vsp1/vsp1_brx.c12
-rw-r--r--drivers/media/platform/vsp1/vsp1_clu.c78
-rw-r--r--drivers/media/platform/vsp1/vsp1_drm.c12
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c24
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.h39
-rw-r--r--drivers/media/platform/vsp1/vsp1_hgo.c12
-rw-r--r--drivers/media/platform/vsp1/vsp1_hgt.c12
-rw-r--r--drivers/media/platform/vsp1/vsp1_hsit.c12
-rw-r--r--drivers/media/platform/vsp1/vsp1_lif.c12
-rw-r--r--drivers/media/platform/vsp1/vsp1_lut.c47
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c168
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.c12
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.c56
-rw-r--r--drivers/media/platform/vsp1/vsp1_uif.c16
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c28
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c302
16 files changed, 422 insertions, 420 deletions
diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c
index 3beec18fd863..011edac5ebc1 100644
--- a/drivers/media/platform/vsp1/vsp1_brx.c
+++ b/drivers/media/platform/vsp1/vsp1_brx.c
@@ -281,19 +281,15 @@ static const struct v4l2_subdev_ops brx_ops = {
281 * VSP1 Entity Operations 281 * VSP1 Entity Operations
282 */ 282 */
283 283
284static void brx_configure(struct vsp1_entity *entity, 284static void brx_configure_stream(struct vsp1_entity *entity,
285 struct vsp1_pipeline *pipe, 285 struct vsp1_pipeline *pipe,
286 struct vsp1_dl_list *dl, 286 struct vsp1_dl_list *dl)
287 enum vsp1_entity_params params)
288{ 287{
289 struct vsp1_brx *brx = to_brx(&entity->subdev); 288 struct vsp1_brx *brx = to_brx(&entity->subdev);
290 struct v4l2_mbus_framefmt *format; 289 struct v4l2_mbus_framefmt *format;
291 unsigned int flags; 290 unsigned int flags;
292 unsigned int i; 291 unsigned int i;
293 292
294 if (params != VSP1_ENTITY_PARAMS_INIT)
295 return;
296
297 format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config, 293 format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config,
298 brx->entity.source_pad); 294 brx->entity.source_pad);
299 295
@@ -400,7 +396,7 @@ static void brx_configure(struct vsp1_entity *entity,
400} 396}
401 397
402static const struct vsp1_entity_operations brx_entity_ops = { 398static const struct vsp1_entity_operations brx_entity_ops = {
403 .configure = brx_configure, 399 .configure_stream = brx_configure_stream,
404}; 400};
405 401
406/* ----------------------------------------------------------------------------- 402/* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c
index ea83f1b7d125..34f17a82ac1f 100644
--- a/drivers/media/platform/vsp1/vsp1_clu.c
+++ b/drivers/media/platform/vsp1/vsp1_clu.c
@@ -169,57 +169,50 @@ static const struct v4l2_subdev_ops clu_ops = {
169 * VSP1 Entity Operations 169 * VSP1 Entity Operations
170 */ 170 */
171 171
172static void clu_configure(struct vsp1_entity *entity, 172static void clu_configure_stream(struct vsp1_entity *entity,
173 struct vsp1_pipeline *pipe, 173 struct vsp1_pipeline *pipe,
174 struct vsp1_dl_list *dl, 174 struct vsp1_dl_list *dl)
175 enum vsp1_entity_params params) 175{
176 struct vsp1_clu *clu = to_clu(&entity->subdev);
177 struct v4l2_mbus_framefmt *format;
178
179 /*
180 * The yuv_mode can't be changed during streaming. Cache it internally
181 * for future runtime configuration calls.
182 */
183 format = vsp1_entity_get_pad_format(&clu->entity,
184 clu->entity.config,
185 CLU_PAD_SINK);
186 clu->yuv_mode = format->code == MEDIA_BUS_FMT_AYUV8_1X32;
187}
188
189static void clu_configure_frame(struct vsp1_entity *entity,
190 struct vsp1_pipeline *pipe,
191 struct vsp1_dl_list *dl)
176{ 192{
177 struct vsp1_clu *clu = to_clu(&entity->subdev); 193 struct vsp1_clu *clu = to_clu(&entity->subdev);
178 struct vsp1_dl_body *dlb; 194 struct vsp1_dl_body *dlb;
179 unsigned long flags; 195 unsigned long flags;
180 u32 ctrl = VI6_CLU_CTRL_AAI | VI6_CLU_CTRL_MVS | VI6_CLU_CTRL_EN; 196 u32 ctrl = VI6_CLU_CTRL_AAI | VI6_CLU_CTRL_MVS | VI6_CLU_CTRL_EN;
181 197
182 switch (params) { 198 /* 2D mode can only be used with the YCbCr pixel encoding. */
183 case VSP1_ENTITY_PARAMS_INIT: { 199 if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode)
184 /* 200 ctrl |= VI6_CLU_CTRL_AX1I_2D | VI6_CLU_CTRL_AX2I_2D
185 * The format can't be changed during streaming, only verify it 201 | VI6_CLU_CTRL_OS0_2D | VI6_CLU_CTRL_OS1_2D
186 * at setup time and store the information internally for future 202 | VI6_CLU_CTRL_OS2_2D | VI6_CLU_CTRL_M2D;
187 * runtime configuration calls.
188 */
189 struct v4l2_mbus_framefmt *format;
190
191 format = vsp1_entity_get_pad_format(&clu->entity,
192 clu->entity.config,
193 CLU_PAD_SINK);
194 clu->yuv_mode = format->code == MEDIA_BUS_FMT_AYUV8_1X32;
195 break;
196 }
197
198 case VSP1_ENTITY_PARAMS_PARTITION:
199 break;
200 203
201 case VSP1_ENTITY_PARAMS_RUNTIME: 204 vsp1_clu_write(clu, dl, VI6_CLU_CTRL, ctrl);
202 /* 2D mode can only be used with the YCbCr pixel encoding. */
203 if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode)
204 ctrl |= VI6_CLU_CTRL_AX1I_2D | VI6_CLU_CTRL_AX2I_2D
205 | VI6_CLU_CTRL_OS0_2D | VI6_CLU_CTRL_OS1_2D
206 | VI6_CLU_CTRL_OS2_2D | VI6_CLU_CTRL_M2D;
207 205
208 vsp1_clu_write(clu, dl, VI6_CLU_CTRL, ctrl); 206 spin_lock_irqsave(&clu->lock, flags);
207 dlb = clu->clu;
208 clu->clu = NULL;
209 spin_unlock_irqrestore(&clu->lock, flags);
209 210
210 spin_lock_irqsave(&clu->lock, flags); 211 if (dlb) {
211 dlb = clu->clu; 212 vsp1_dl_list_add_body(dl, dlb);
212 clu->clu = NULL;
213 spin_unlock_irqrestore(&clu->lock, flags);
214 213
215 if (dlb) { 214 /* Release our local reference. */
216 vsp1_dl_list_add_body(dl, dlb); 215 vsp1_dl_body_put(dlb);
217
218 /* Release our local reference. */
219 vsp1_dl_body_put(dlb);
220 }
221
222 break;
223 } 216 }
224} 217}
225 218
@@ -231,7 +224,8 @@ static void clu_destroy(struct vsp1_entity *entity)
231} 224}
232 225
233static const struct vsp1_entity_operations clu_entity_ops = { 226static const struct vsp1_entity_operations clu_entity_ops = {
234 .configure = clu_configure, 227 .configure_stream = clu_configure_stream,
228 .configure_frame = clu_configure_frame,
235 .destroy = clu_destroy, 229 .destroy = clu_destroy,
236}; 230};
237 231
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 68e8830f27fa..32ab98f101c1 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -552,15 +552,9 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
552 } 552 }
553 553
554 vsp1_entity_route_setup(entity, pipe, dl); 554 vsp1_entity_route_setup(entity, pipe, dl);
555 555 vsp1_entity_configure_stream(entity, pipe, dl);
556 if (entity->ops->configure) { 556 vsp1_entity_configure_frame(entity, pipe, dl);
557 entity->ops->configure(entity, pipe, dl, 557 vsp1_entity_configure_partition(entity, pipe, dl);
558 VSP1_ENTITY_PARAMS_INIT);
559 entity->ops->configure(entity, pipe, dl,
560 VSP1_ENTITY_PARAMS_RUNTIME);
561 entity->ops->configure(entity, pipe, dl,
562 VSP1_ENTITY_PARAMS_PARTITION);
563 }
564 } 558 }
565 559
566 vsp1_dl_list_commit(dl, drm_pipe->force_brx_release); 560 vsp1_dl_list_commit(dl, drm_pipe->force_brx_release);
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index c411643695e4..73f6611ec279 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -69,6 +69,30 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity,
69 vsp1_dl_list_write(dl, source->route->reg, route); 69 vsp1_dl_list_write(dl, source->route->reg, route);
70} 70}
71 71
72void vsp1_entity_configure_stream(struct vsp1_entity *entity,
73 struct vsp1_pipeline *pipe,
74 struct vsp1_dl_list *dl)
75{
76 if (entity->ops->configure_stream)
77 entity->ops->configure_stream(entity, pipe, dl);
78}
79
80void vsp1_entity_configure_frame(struct vsp1_entity *entity,
81 struct vsp1_pipeline *pipe,
82 struct vsp1_dl_list *dl)
83{
84 if (entity->ops->configure_frame)
85 entity->ops->configure_frame(entity, pipe, dl);
86}
87
88void vsp1_entity_configure_partition(struct vsp1_entity *entity,
89 struct vsp1_pipeline *pipe,
90 struct vsp1_dl_list *dl)
91{
92 if (entity->ops->configure_partition)
93 entity->ops->configure_partition(entity, pipe, dl);
94}
95
72/* ----------------------------------------------------------------------------- 96/* -----------------------------------------------------------------------------
73 * V4L2 Subdevice Operations 97 * V4L2 Subdevice Operations
74 */ 98 */
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 94490d697dcf..c29676671b1a 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -37,18 +37,6 @@ enum vsp1_entity_type {
37 VSP1_ENTITY_WPF, 37 VSP1_ENTITY_WPF,
38}; 38};
39 39
40/**
41 * enum vsp1_entity_params - Entity configuration parameters class
42 * @VSP1_ENTITY_PARAMS_INIT - Initial parameters
43 * @VSP1_ENTITY_PARAMS_PARTITION - Per-image partition parameters
44 * @VSP1_ENTITY_PARAMS_RUNTIME - Runtime-configurable parameters
45 */
46enum vsp1_entity_params {
47 VSP1_ENTITY_PARAMS_INIT,
48 VSP1_ENTITY_PARAMS_PARTITION,
49 VSP1_ENTITY_PARAMS_RUNTIME,
50};
51
52#define VSP1_ENTITY_MAX_INPUTS 5 /* For the BRU */ 40#define VSP1_ENTITY_MAX_INPUTS 5 /* For the BRU */
53 41
54/* 42/*
@@ -77,8 +65,10 @@ struct vsp1_route {
77/** 65/**
78 * struct vsp1_entity_operations - Entity operations 66 * struct vsp1_entity_operations - Entity operations
79 * @destroy: Destroy the entity. 67 * @destroy: Destroy the entity.
80 * @configure: Setup the hardware based on the entity state (pipeline, formats, 68 * @configure_stream: Setup the hardware parameters for the stream which do
81 * selection rectangles, ...) 69 * not vary between frames (pipeline, formats).
70 * @configure_frame: Configure the runtime parameters for each frame.
71 * @configure_partition: Configure partition specific parameters.
82 * @max_width: Return the max supported width of data that the entity can 72 * @max_width: Return the max supported width of data that the entity can
83 * process in a single operation. 73 * process in a single operation.
84 * @partition: Process the partition construction based on this entity's 74 * @partition: Process the partition construction based on this entity's
@@ -86,8 +76,13 @@ struct vsp1_route {
86 */ 76 */
87struct vsp1_entity_operations { 77struct vsp1_entity_operations {
88 void (*destroy)(struct vsp1_entity *); 78 void (*destroy)(struct vsp1_entity *);
89 void (*configure)(struct vsp1_entity *, struct vsp1_pipeline *, 79 void (*configure_stream)(struct vsp1_entity *, struct vsp1_pipeline *,
90 struct vsp1_dl_list *, enum vsp1_entity_params); 80 struct vsp1_dl_list *);
81 void (*configure_frame)(struct vsp1_entity *, struct vsp1_pipeline *,
82 struct vsp1_dl_list *);
83 void (*configure_partition)(struct vsp1_entity *,
84 struct vsp1_pipeline *,
85 struct vsp1_dl_list *);
91 unsigned int (*max_width)(struct vsp1_entity *, struct vsp1_pipeline *); 86 unsigned int (*max_width)(struct vsp1_entity *, struct vsp1_pipeline *);
92 void (*partition)(struct vsp1_entity *, struct vsp1_pipeline *, 87 void (*partition)(struct vsp1_entity *, struct vsp1_pipeline *,
93 struct vsp1_partition *, unsigned int, 88 struct vsp1_partition *, unsigned int,
@@ -156,6 +151,18 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity,
156 struct vsp1_pipeline *pipe, 151 struct vsp1_pipeline *pipe,
157 struct vsp1_dl_list *dl); 152 struct vsp1_dl_list *dl);
158 153
154void vsp1_entity_configure_stream(struct vsp1_entity *entity,
155 struct vsp1_pipeline *pipe,
156 struct vsp1_dl_list *dl);
157
158void vsp1_entity_configure_frame(struct vsp1_entity *entity,
159 struct vsp1_pipeline *pipe,
160 struct vsp1_dl_list *dl);
161
162void vsp1_entity_configure_partition(struct vsp1_entity *entity,
163 struct vsp1_pipeline *pipe,
164 struct vsp1_dl_list *dl);
165
159struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad); 166struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad);
160 167
161int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, 168int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
diff --git a/drivers/media/platform/vsp1/vsp1_hgo.c b/drivers/media/platform/vsp1/vsp1_hgo.c
index d514807ccdf4..8855ad15d132 100644
--- a/drivers/media/platform/vsp1/vsp1_hgo.c
+++ b/drivers/media/platform/vsp1/vsp1_hgo.c
@@ -129,10 +129,9 @@ static const struct v4l2_ctrl_config hgo_num_bins_control = {
129 * VSP1 Entity Operations 129 * VSP1 Entity Operations
130 */ 130 */
131 131
132static void hgo_configure(struct vsp1_entity *entity, 132static void hgo_configure_stream(struct vsp1_entity *entity,
133 struct vsp1_pipeline *pipe, 133 struct vsp1_pipeline *pipe,
134 struct vsp1_dl_list *dl, 134 struct vsp1_dl_list *dl)
135 enum vsp1_entity_params params)
136{ 135{
137 struct vsp1_hgo *hgo = to_hgo(&entity->subdev); 136 struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
138 struct v4l2_rect *compose; 137 struct v4l2_rect *compose;
@@ -140,9 +139,6 @@ static void hgo_configure(struct vsp1_entity *entity,
140 unsigned int hratio; 139 unsigned int hratio;
141 unsigned int vratio; 140 unsigned int vratio;
142 141
143 if (params != VSP1_ENTITY_PARAMS_INIT)
144 return;
145
146 crop = vsp1_entity_get_pad_selection(entity, entity->config, 142 crop = vsp1_entity_get_pad_selection(entity, entity->config,
147 HISTO_PAD_SINK, V4L2_SEL_TGT_CROP); 143 HISTO_PAD_SINK, V4L2_SEL_TGT_CROP);
148 compose = vsp1_entity_get_pad_selection(entity, entity->config, 144 compose = vsp1_entity_get_pad_selection(entity, entity->config,
@@ -174,7 +170,7 @@ static void hgo_configure(struct vsp1_entity *entity,
174} 170}
175 171
176static const struct vsp1_entity_operations hgo_entity_ops = { 172static const struct vsp1_entity_operations hgo_entity_ops = {
177 .configure = hgo_configure, 173 .configure_stream = hgo_configure_stream,
178 .destroy = vsp1_histogram_destroy, 174 .destroy = vsp1_histogram_destroy,
179}; 175};
180 176
diff --git a/drivers/media/platform/vsp1/vsp1_hgt.c b/drivers/media/platform/vsp1/vsp1_hgt.c
index 18dc89f47c45..a7ec2c9fdc5c 100644
--- a/drivers/media/platform/vsp1/vsp1_hgt.c
+++ b/drivers/media/platform/vsp1/vsp1_hgt.c
@@ -125,10 +125,9 @@ static const struct v4l2_ctrl_config hgt_hue_areas = {
125 * VSP1 Entity Operations 125 * VSP1 Entity Operations
126 */ 126 */
127 127
128static void hgt_configure(struct vsp1_entity *entity, 128static void hgt_configure_stream(struct vsp1_entity *entity,
129 struct vsp1_pipeline *pipe, 129 struct vsp1_pipeline *pipe,
130 struct vsp1_dl_list *dl, 130 struct vsp1_dl_list *dl)
131 enum vsp1_entity_params params)
132{ 131{
133 struct vsp1_hgt *hgt = to_hgt(&entity->subdev); 132 struct vsp1_hgt *hgt = to_hgt(&entity->subdev);
134 struct v4l2_rect *compose; 133 struct v4l2_rect *compose;
@@ -139,9 +138,6 @@ static void hgt_configure(struct vsp1_entity *entity,
139 u8 upper; 138 u8 upper;
140 unsigned int i; 139 unsigned int i;
141 140
142 if (params != VSP1_ENTITY_PARAMS_INIT)
143 return;
144
145 crop = vsp1_entity_get_pad_selection(entity, entity->config, 141 crop = vsp1_entity_get_pad_selection(entity, entity->config,
146 HISTO_PAD_SINK, V4L2_SEL_TGT_CROP); 142 HISTO_PAD_SINK, V4L2_SEL_TGT_CROP);
147 compose = vsp1_entity_get_pad_selection(entity, entity->config, 143 compose = vsp1_entity_get_pad_selection(entity, entity->config,
@@ -175,7 +171,7 @@ static void hgt_configure(struct vsp1_entity *entity,
175} 171}
176 172
177static const struct vsp1_entity_operations hgt_entity_ops = { 173static const struct vsp1_entity_operations hgt_entity_ops = {
178 .configure = hgt_configure, 174 .configure_stream = hgt_configure_stream,
179 .destroy = vsp1_histogram_destroy, 175 .destroy = vsp1_histogram_destroy,
180}; 176};
181 177
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index 7ba3535f3c9b..798c1448e3dc 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -127,16 +127,12 @@ static const struct v4l2_subdev_ops hsit_ops = {
127 * VSP1 Entity Operations 127 * VSP1 Entity Operations
128 */ 128 */
129 129
130static void hsit_configure(struct vsp1_entity *entity, 130static void hsit_configure_stream(struct vsp1_entity *entity,
131 struct vsp1_pipeline *pipe, 131 struct vsp1_pipeline *pipe,
132 struct vsp1_dl_list *dl, 132 struct vsp1_dl_list *dl)
133 enum vsp1_entity_params params)
134{ 133{
135 struct vsp1_hsit *hsit = to_hsit(&entity->subdev); 134 struct vsp1_hsit *hsit = to_hsit(&entity->subdev);
136 135
137 if (params != VSP1_ENTITY_PARAMS_INIT)
138 return;
139
140 if (hsit->inverse) 136 if (hsit->inverse)
141 vsp1_hsit_write(hsit, dl, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); 137 vsp1_hsit_write(hsit, dl, VI6_HSI_CTRL, VI6_HSI_CTRL_EN);
142 else 138 else
@@ -144,7 +140,7 @@ static void hsit_configure(struct vsp1_entity *entity,
144} 140}
145 141
146static const struct vsp1_entity_operations hsit_entity_ops = { 142static const struct vsp1_entity_operations hsit_entity_ops = {
147 .configure = hsit_configure, 143 .configure_stream = hsit_configure_stream,
148}; 144};
149 145
150/* ----------------------------------------------------------------------------- 146/* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index fbdd5715f829..5a3f3e7b9bd3 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -81,10 +81,9 @@ static const struct v4l2_subdev_ops lif_ops = {
81 * VSP1 Entity Operations 81 * VSP1 Entity Operations
82 */ 82 */
83 83
84static void lif_configure(struct vsp1_entity *entity, 84static void lif_configure_stream(struct vsp1_entity *entity,
85 struct vsp1_pipeline *pipe, 85 struct vsp1_pipeline *pipe,
86 struct vsp1_dl_list *dl, 86 struct vsp1_dl_list *dl)
87 enum vsp1_entity_params params)
88{ 87{
89 const struct v4l2_mbus_framefmt *format; 88 const struct v4l2_mbus_framefmt *format;
90 struct vsp1_lif *lif = to_lif(&entity->subdev); 89 struct vsp1_lif *lif = to_lif(&entity->subdev);
@@ -92,9 +91,6 @@ static void lif_configure(struct vsp1_entity *entity,
92 unsigned int obth = 400; 91 unsigned int obth = 400;
93 unsigned int lbth = 200; 92 unsigned int lbth = 200;
94 93
95 if (params != VSP1_ENTITY_PARAMS_INIT)
96 return;
97
98 format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, 94 format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config,
99 LIF_PAD_SOURCE); 95 LIF_PAD_SOURCE);
100 96
@@ -123,7 +119,7 @@ static void lif_configure(struct vsp1_entity *entity,
123} 119}
124 120
125static const struct vsp1_entity_operations lif_entity_ops = { 121static const struct vsp1_entity_operations lif_entity_ops = {
126 .configure = lif_configure, 122 .configure_stream = lif_configure_stream,
127}; 123};
128 124
129/* ----------------------------------------------------------------------------- 125/* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index b3ea90172439..1b62f54dc302 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -145,37 +145,33 @@ static const struct v4l2_subdev_ops lut_ops = {
145 * VSP1 Entity Operations 145 * VSP1 Entity Operations
146 */ 146 */
147 147
148static void lut_configure(struct vsp1_entity *entity, 148static void lut_configure_stream(struct vsp1_entity *entity,
149 struct vsp1_pipeline *pipe, 149 struct vsp1_pipeline *pipe,
150 struct vsp1_dl_list *dl, 150 struct vsp1_dl_list *dl)
151 enum vsp1_entity_params params)
152{ 151{
153 struct vsp1_lut *lut = to_lut(&entity->subdev); 152 struct vsp1_lut *lut = to_lut(&entity->subdev);
154 struct vsp1_dl_body *dlb;
155 unsigned long flags;
156
157 switch (params) {
158 case VSP1_ENTITY_PARAMS_INIT:
159 vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN);
160 break;
161 153
162 case VSP1_ENTITY_PARAMS_PARTITION: 154 vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN);
163 break; 155}
164 156
165 case VSP1_ENTITY_PARAMS_RUNTIME: 157static void lut_configure_frame(struct vsp1_entity *entity,
166 spin_lock_irqsave(&lut->lock, flags); 158 struct vsp1_pipeline *pipe,
167 dlb = lut->lut; 159 struct vsp1_dl_list *dl)
168 lut->lut = NULL; 160{
169 spin_unlock_irqrestore(&lut->lock, flags); 161 struct vsp1_lut *lut = to_lut(&entity->subdev);
162 struct vsp1_dl_body *dlb;
163 unsigned long flags;
170 164
171 if (dlb) { 165 spin_lock_irqsave(&lut->lock, flags);
172 vsp1_dl_list_add_body(dl, dlb); 166 dlb = lut->lut;
167 lut->lut = NULL;
168 spin_unlock_irqrestore(&lut->lock, flags);
173 169
174 /* Release our local reference. */ 170 if (dlb) {
175 vsp1_dl_body_put(dlb); 171 vsp1_dl_list_add_body(dl, dlb);
176 }
177 172
178 break; 173 /* Release our local reference. */
174 vsp1_dl_body_put(dlb);
179 } 175 }
180} 176}
181 177
@@ -187,7 +183,8 @@ static void lut_destroy(struct vsp1_entity *entity)
187} 183}
188 184
189static const struct vsp1_entity_operations lut_entity_ops = { 185static const struct vsp1_entity_operations lut_entity_ops = {
190 .configure = lut_configure, 186 .configure_stream = lut_configure_stream,
187 .configure_frame = lut_configure_frame,
191 .destroy = lut_destroy, 188 .destroy = lut_destroy,
192}; 189};
193 190
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 7005a4c6aa88..deb86cc235ef 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -42,10 +42,9 @@ static const struct v4l2_subdev_ops rpf_ops = {
42 * VSP1 Entity Operations 42 * VSP1 Entity Operations
43 */ 43 */
44 44
45static void rpf_configure(struct vsp1_entity *entity, 45static void rpf_configure_stream(struct vsp1_entity *entity,
46 struct vsp1_pipeline *pipe, 46 struct vsp1_pipeline *pipe,
47 struct vsp1_dl_list *dl, 47 struct vsp1_dl_list *dl)
48 enum vsp1_entity_params params)
49{ 48{
50 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); 49 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
51 const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; 50 const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
@@ -57,80 +56,6 @@ static void rpf_configure(struct vsp1_entity *entity,
57 u32 pstride; 56 u32 pstride;
58 u32 infmt; 57 u32 infmt;
59 58
60 if (params == VSP1_ENTITY_PARAMS_RUNTIME) {
61 vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET,
62 rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
63 vsp1_rpf_write(rpf, dl, VI6_RPF_MULT_ALPHA, rpf->mult_alpha |
64 (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT));
65
66 vsp1_pipeline_propagate_alpha(pipe, dl, rpf->alpha);
67 return;
68 }
69
70 if (params == VSP1_ENTITY_PARAMS_PARTITION) {
71 struct vsp1_device *vsp1 = rpf->entity.vsp1;
72 struct vsp1_rwpf_memory mem = rpf->mem;
73 struct v4l2_rect crop;
74
75 /*
76 * Source size and crop offsets.
77 *
78 * The crop offsets correspond to the location of the crop
79 * rectangle top left corner in the plane buffer. Only two
80 * offsets are needed, as planes 2 and 3 always have identical
81 * strides.
82 */
83 crop = *vsp1_rwpf_get_crop(rpf, rpf->entity.config);
84
85 /*
86 * Partition Algorithm Control
87 *
88 * The partition algorithm can split this frame into multiple
89 * slices. We must scale our partition window based on the pipe
90 * configuration to match the destination partition window.
91 * To achieve this, we adjust our crop to provide a 'sub-crop'
92 * matching the expected partition window. Only 'left' and
93 * 'width' need to be adjusted.
94 */
95 if (pipe->partitions > 1) {
96 crop.width = pipe->partition->rpf.width;
97 crop.left += pipe->partition->rpf.left;
98 }
99
100 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE,
101 (crop.width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
102 (crop.height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
103 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE,
104 (crop.width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
105 (crop.height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
106
107 mem.addr[0] += crop.top * format->plane_fmt[0].bytesperline
108 + crop.left * fmtinfo->bpp[0] / 8;
109
110 if (format->num_planes > 1) {
111 unsigned int offset;
112
113 offset = crop.top * format->plane_fmt[1].bytesperline
114 + crop.left / fmtinfo->hsub
115 * fmtinfo->bpp[1] / 8;
116 mem.addr[1] += offset;
117 mem.addr[2] += offset;
118 }
119
120 /*
121 * On Gen3 hardware the SPUVS bit has no effect on 3-planar
122 * formats. Swap the U and V planes manually in that case.
123 */
124 if (vsp1->info->gen == 3 && format->num_planes == 3 &&
125 fmtinfo->swap_uv)
126 swap(mem.addr[1], mem.addr[2]);
127
128 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y, mem.addr[0]);
129 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0, mem.addr[1]);
130 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1, mem.addr[2]);
131 return;
132 }
133
134 /* Stride */ 59 /* Stride */
135 pstride = format->plane_fmt[0].bytesperline 60 pstride = format->plane_fmt[0].bytesperline
136 << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; 61 << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT;
@@ -243,6 +168,89 @@ static void rpf_configure(struct vsp1_entity *entity,
243 168
244} 169}
245 170
171static void rpf_configure_frame(struct vsp1_entity *entity,
172 struct vsp1_pipeline *pipe,
173 struct vsp1_dl_list *dl)
174{
175 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
176
177 vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET,
178 rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
179 vsp1_rpf_write(rpf, dl, VI6_RPF_MULT_ALPHA, rpf->mult_alpha |
180 (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT));
181
182 vsp1_pipeline_propagate_alpha(pipe, dl, rpf->alpha);
183}
184
185static void rpf_configure_partition(struct vsp1_entity *entity,
186 struct vsp1_pipeline *pipe,
187 struct vsp1_dl_list *dl)
188{
189 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
190 struct vsp1_rwpf_memory mem = rpf->mem;
191 struct vsp1_device *vsp1 = rpf->entity.vsp1;
192 const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
193 const struct v4l2_pix_format_mplane *format = &rpf->format;
194 struct v4l2_rect crop;
195
196 /*
197 * Source size and crop offsets.
198 *
199 * The crop offsets correspond to the location of the crop
200 * rectangle top left corner in the plane buffer. Only two
201 * offsets are needed, as planes 2 and 3 always have identical
202 * strides.
203 */
204 crop = *vsp1_rwpf_get_crop(rpf, rpf->entity.config);
205
206 /*
207 * Partition Algorithm Control
208 *
209 * The partition algorithm can split this frame into multiple
210 * slices. We must scale our partition window based on the pipe
211 * configuration to match the destination partition window.
212 * To achieve this, we adjust our crop to provide a 'sub-crop'
213 * matching the expected partition window. Only 'left' and
214 * 'width' need to be adjusted.
215 */
216 if (pipe->partitions > 1) {
217 crop.width = pipe->partition->rpf.width;
218 crop.left += pipe->partition->rpf.left;
219 }
220
221 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE,
222 (crop.width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
223 (crop.height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
224 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE,
225 (crop.width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
226 (crop.height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
227
228 mem.addr[0] += crop.top * format->plane_fmt[0].bytesperline
229 + crop.left * fmtinfo->bpp[0] / 8;
230
231 if (format->num_planes > 1) {
232 unsigned int offset;
233
234 offset = crop.top * format->plane_fmt[1].bytesperline
235 + crop.left / fmtinfo->hsub
236 * fmtinfo->bpp[1] / 8;
237 mem.addr[1] += offset;
238 mem.addr[2] += offset;
239 }
240
241 /*
242 * On Gen3 hardware the SPUVS bit has no effect on 3-planar
243 * formats. Swap the U and V planes manually in that case.
244 */
245 if (vsp1->info->gen == 3 && format->num_planes == 3 &&
246 fmtinfo->swap_uv)
247 swap(mem.addr[1], mem.addr[2]);
248
249 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y, mem.addr[0]);
250 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0, mem.addr[1]);
251 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1, mem.addr[2]);
252}
253
246static void rpf_partition(struct vsp1_entity *entity, 254static void rpf_partition(struct vsp1_entity *entity,
247 struct vsp1_pipeline *pipe, 255 struct vsp1_pipeline *pipe,
248 struct vsp1_partition *partition, 256 struct vsp1_partition *partition,
@@ -253,7 +261,9 @@ static void rpf_partition(struct vsp1_entity *entity,
253} 261}
254 262
255static const struct vsp1_entity_operations rpf_entity_ops = { 263static const struct vsp1_entity_operations rpf_entity_ops = {
256 .configure = rpf_configure, 264 .configure_stream = rpf_configure_stream,
265 .configure_frame = rpf_configure_frame,
266 .configure_partition = rpf_configure_partition,
257 .partition = rpf_partition, 267 .partition = rpf_partition,
258}; 268};
259 269
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index 44cb9b134a19..d29f63dfc17e 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -267,10 +267,9 @@ static const struct v4l2_subdev_ops sru_ops = {
267 * VSP1 Entity Operations 267 * VSP1 Entity Operations
268 */ 268 */
269 269
270static void sru_configure(struct vsp1_entity *entity, 270static void sru_configure_stream(struct vsp1_entity *entity,
271 struct vsp1_pipeline *pipe, 271 struct vsp1_pipeline *pipe,
272 struct vsp1_dl_list *dl, 272 struct vsp1_dl_list *dl)
273 enum vsp1_entity_params params)
274{ 273{
275 const struct vsp1_sru_param *param; 274 const struct vsp1_sru_param *param;
276 struct vsp1_sru *sru = to_sru(&entity->subdev); 275 struct vsp1_sru *sru = to_sru(&entity->subdev);
@@ -278,9 +277,6 @@ static void sru_configure(struct vsp1_entity *entity,
278 struct v4l2_mbus_framefmt *output; 277 struct v4l2_mbus_framefmt *output;
279 u32 ctrl0; 278 u32 ctrl0;
280 279
281 if (params != VSP1_ENTITY_PARAMS_INIT)
282 return;
283
284 input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, 280 input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
285 SRU_PAD_SINK); 281 SRU_PAD_SINK);
286 output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, 282 output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
@@ -347,7 +343,7 @@ static void sru_partition(struct vsp1_entity *entity,
347} 343}
348 344
349static const struct vsp1_entity_operations sru_entity_ops = { 345static const struct vsp1_entity_operations sru_entity_ops = {
350 .configure = sru_configure, 346 .configure_stream = sru_configure_stream,
351 .max_width = sru_max_width, 347 .max_width = sru_max_width,
352 .partition = sru_partition, 348 .partition = sru_partition,
353}; 349};
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index e5afd69df939..c81ce9e5bff3 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -255,10 +255,9 @@ static const struct v4l2_subdev_ops uds_ops = {
255 * VSP1 Entity Operations 255 * VSP1 Entity Operations
256 */ 256 */
257 257
258static void uds_configure(struct vsp1_entity *entity, 258static void uds_configure_stream(struct vsp1_entity *entity,
259 struct vsp1_pipeline *pipe, 259 struct vsp1_pipeline *pipe,
260 struct vsp1_dl_list *dl, 260 struct vsp1_dl_list *dl)
261 enum vsp1_entity_params params)
262{ 261{
263 struct vsp1_uds *uds = to_uds(&entity->subdev); 262 struct vsp1_uds *uds = to_uds(&entity->subdev);
264 const struct v4l2_mbus_framefmt *output; 263 const struct v4l2_mbus_framefmt *output;
@@ -272,27 +271,6 @@ static void uds_configure(struct vsp1_entity *entity,
272 output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, 271 output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
273 UDS_PAD_SOURCE); 272 UDS_PAD_SOURCE);
274 273
275 if (params == VSP1_ENTITY_PARAMS_PARTITION) {
276 struct vsp1_partition *partition = pipe->partition;
277
278 /* Input size clipping */
279 vsp1_uds_write(uds, dl, VI6_UDS_HSZCLIP, VI6_UDS_HSZCLIP_HCEN |
280 (0 << VI6_UDS_HSZCLIP_HCL_OFST_SHIFT) |
281 (partition->uds_sink.width
282 << VI6_UDS_HSZCLIP_HCL_SIZE_SHIFT));
283
284 /* Output size clipping */
285 vsp1_uds_write(uds, dl, VI6_UDS_CLIP_SIZE,
286 (partition->uds_source.width
287 << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
288 (output->height
289 << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
290 return;
291 }
292
293 if (params != VSP1_ENTITY_PARAMS_INIT)
294 return;
295
296 hscale = uds_compute_ratio(input->width, output->width); 274 hscale = uds_compute_ratio(input->width, output->width);
297 vscale = uds_compute_ratio(input->height, output->height); 275 vscale = uds_compute_ratio(input->height, output->height);
298 276
@@ -324,6 +302,31 @@ static void uds_configure(struct vsp1_entity *entity,
324 (vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); 302 (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
325} 303}
326 304
305static void uds_configure_partition(struct vsp1_entity *entity,
306 struct vsp1_pipeline *pipe,
307 struct vsp1_dl_list *dl)
308{
309 struct vsp1_uds *uds = to_uds(&entity->subdev);
310 struct vsp1_partition *partition = pipe->partition;
311 const struct v4l2_mbus_framefmt *output;
312
313 output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
314 UDS_PAD_SOURCE);
315
316 /* Input size clipping */
317 vsp1_uds_write(uds, dl, VI6_UDS_HSZCLIP, VI6_UDS_HSZCLIP_HCEN |
318 (0 << VI6_UDS_HSZCLIP_HCL_OFST_SHIFT) |
319 (partition->uds_sink.width
320 << VI6_UDS_HSZCLIP_HCL_SIZE_SHIFT));
321
322 /* Output size clipping */
323 vsp1_uds_write(uds, dl, VI6_UDS_CLIP_SIZE,
324 (partition->uds_source.width
325 << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
326 (output->height
327 << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
328}
329
327static unsigned int uds_max_width(struct vsp1_entity *entity, 330static unsigned int uds_max_width(struct vsp1_entity *entity,
328 struct vsp1_pipeline *pipe) 331 struct vsp1_pipeline *pipe)
329{ 332{
@@ -380,7 +383,8 @@ static void uds_partition(struct vsp1_entity *entity,
380} 383}
381 384
382static const struct vsp1_entity_operations uds_entity_ops = { 385static const struct vsp1_entity_operations uds_entity_ops = {
383 .configure = uds_configure, 386 .configure_stream = uds_configure_stream,
387 .configure_partition = uds_configure_partition,
384 .max_width = uds_max_width, 388 .max_width = uds_max_width,
385 .partition = uds_partition, 389 .partition = uds_partition,
386}; 390};
diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c
index c219165b15b9..c526e484b326 100644
--- a/drivers/media/platform/vsp1/vsp1_uif.c
+++ b/drivers/media/platform/vsp1/vsp1_uif.c
@@ -189,23 +189,15 @@ static const struct v4l2_subdev_ops uif_ops = {
189 * VSP1 Entity Operations 189 * VSP1 Entity Operations
190 */ 190 */
191 191
192static void uif_configure(struct vsp1_entity *entity, 192static void uif_configure_stream(struct vsp1_entity *entity,
193 struct vsp1_pipeline *pipe, 193 struct vsp1_pipeline *pipe,
194 struct vsp1_dl_list *dl, 194 struct vsp1_dl_list *dl)
195 enum vsp1_entity_params params)
196{ 195{
197 struct vsp1_uif *uif = to_uif(&entity->subdev); 196 struct vsp1_uif *uif = to_uif(&entity->subdev);
198 const struct v4l2_rect *crop; 197 const struct v4l2_rect *crop;
199 unsigned int left; 198 unsigned int left;
200 unsigned int width; 199 unsigned int width;
201 200
202 /*
203 * Per-partition configuration isn't needed as the DISCOM is used in
204 * display pipelines only.
205 */
206 if (params != VSP1_ENTITY_PARAMS_INIT)
207 return;
208
209 vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR, 201 vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR,
210 VI6_UIF_DISCOM_DOCMPMR_SEL(9)); 202 VI6_UIF_DISCOM_DOCMPMR_SEL(9));
211 203
@@ -231,7 +223,7 @@ static void uif_configure(struct vsp1_entity *entity,
231} 223}
232 224
233static const struct vsp1_entity_operations uif_entity_ops = { 225static const struct vsp1_entity_operations uif_entity_ops = {
234 .configure = uif_configure, 226 .configure_stream = uif_configure_stream,
235}; 227};
236 228
237/* ----------------------------------------------------------------------------- 229/* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 5deb35210055..c457d0626588 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -382,11 +382,8 @@ static void vsp1_video_pipeline_run_partition(struct vsp1_pipeline *pipe,
382 382
383 pipe->partition = &pipe->part_table[partition]; 383 pipe->partition = &pipe->part_table[partition];
384 384
385 list_for_each_entry(entity, &pipe->entities, list_pipe) { 385 list_for_each_entry(entity, &pipe->entities, list_pipe)
386 if (entity->ops->configure) 386 vsp1_entity_configure_partition(entity, pipe, dl);
387 entity->ops->configure(entity, pipe, dl,
388 VSP1_ENTITY_PARAMS_PARTITION);
389 }
390} 387}
391 388
392static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) 389static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
@@ -398,21 +395,13 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
398 if (!pipe->dl) 395 if (!pipe->dl)
399 pipe->dl = vsp1_dl_list_get(pipe->output->dlm); 396 pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
400 397
401 /* 398 list_for_each_entry(entity, &pipe->entities, list_pipe)
402 * Start with the runtime parameters as the configure operation can 399 vsp1_entity_configure_frame(entity, pipe, pipe->dl);
403 * compute/cache information needed when configuring partitions. This
404 * is the case with flipping in the WPF.
405 */
406 list_for_each_entry(entity, &pipe->entities, list_pipe) {
407 if (entity->ops->configure)
408 entity->ops->configure(entity, pipe, pipe->dl,
409 VSP1_ENTITY_PARAMS_RUNTIME);
410 }
411 400
412 /* Run the first partition */ 401 /* Run the first partition. */
413 vsp1_video_pipeline_run_partition(pipe, pipe->dl, 0); 402 vsp1_video_pipeline_run_partition(pipe, pipe->dl, 0);
414 403
415 /* Process consecutive partitions as necessary */ 404 /* Process consecutive partitions as necessary. */
416 for (partition = 1; partition < pipe->partitions; ++partition) { 405 for (partition = 1; partition < pipe->partitions; ++partition) {
417 struct vsp1_dl_list *dl; 406 struct vsp1_dl_list *dl;
418 407
@@ -833,10 +822,7 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
833 822
834 list_for_each_entry(entity, &pipe->entities, list_pipe) { 823 list_for_each_entry(entity, &pipe->entities, list_pipe) {
835 vsp1_entity_route_setup(entity, pipe, pipe->dl); 824 vsp1_entity_route_setup(entity, pipe, pipe->dl);
836 825 vsp1_entity_configure_stream(entity, pipe, pipe->dl);
837 if (entity->ops->configure)
838 entity->ops->configure(entity, pipe, pipe->dl,
839 VSP1_ENTITY_PARAMS_INIT);
840 } 826 }
841 827
842 return 0; 828 return 0;
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 65ed2f849551..8662c5d2fc64 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -232,10 +232,9 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity)
232 vsp1_dlm_destroy(wpf->dlm); 232 vsp1_dlm_destroy(wpf->dlm);
233} 233}
234 234
235static void wpf_configure(struct vsp1_entity *entity, 235static void wpf_configure_stream(struct vsp1_entity *entity,
236 struct vsp1_pipeline *pipe, 236 struct vsp1_pipeline *pipe,
237 struct vsp1_dl_list *dl, 237 struct vsp1_dl_list *dl)
238 enum vsp1_entity_params params)
239{ 238{
240 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); 239 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
241 struct vsp1_device *vsp1 = wpf->entity.vsp1; 240 struct vsp1_device *vsp1 = wpf->entity.vsp1;
@@ -245,149 +244,12 @@ static void wpf_configure(struct vsp1_entity *entity,
245 u32 outfmt = 0; 244 u32 outfmt = 0;
246 u32 srcrpf = 0; 245 u32 srcrpf = 0;
247 246
248 if (params == VSP1_ENTITY_PARAMS_RUNTIME) {
249 const unsigned int mask = BIT(WPF_CTRL_VFLIP)
250 | BIT(WPF_CTRL_HFLIP);
251 unsigned long flags;
252
253 spin_lock_irqsave(&wpf->flip.lock, flags);
254 wpf->flip.active = (wpf->flip.active & ~mask)
255 | (wpf->flip.pending & mask);
256 spin_unlock_irqrestore(&wpf->flip.lock, flags);
257
258 outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt;
259
260 if (wpf->flip.active & BIT(WPF_CTRL_VFLIP))
261 outfmt |= VI6_WPF_OUTFMT_FLP;
262 if (wpf->flip.active & BIT(WPF_CTRL_HFLIP))
263 outfmt |= VI6_WPF_OUTFMT_HFLP;
264
265 vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt);
266 return;
267 }
268
269 sink_format = vsp1_entity_get_pad_format(&wpf->entity, 247 sink_format = vsp1_entity_get_pad_format(&wpf->entity,
270 wpf->entity.config, 248 wpf->entity.config,
271 RWPF_PAD_SINK); 249 RWPF_PAD_SINK);
272 source_format = vsp1_entity_get_pad_format(&wpf->entity, 250 source_format = vsp1_entity_get_pad_format(&wpf->entity,
273 wpf->entity.config, 251 wpf->entity.config,
274 RWPF_PAD_SOURCE); 252 RWPF_PAD_SOURCE);
275
276 if (params == VSP1_ENTITY_PARAMS_PARTITION) {
277 const struct v4l2_pix_format_mplane *format = &wpf->format;
278 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
279 struct vsp1_rwpf_memory mem = wpf->mem;
280 unsigned int flip = wpf->flip.active;
281 unsigned int width = sink_format->width;
282 unsigned int height = sink_format->height;
283 unsigned int offset;
284
285 /*
286 * Cropping. The partition algorithm can split the image into
287 * multiple slices.
288 */
289 if (pipe->partitions > 1)
290 width = pipe->partition->wpf.width;
291
292 vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN |
293 (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
294 (width << VI6_WPF_SZCLIP_SIZE_SHIFT));
295 vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN |
296 (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
297 (height << VI6_WPF_SZCLIP_SIZE_SHIFT));
298
299 if (pipe->lif)
300 return;
301
302 /*
303 * Update the memory offsets based on flipping configuration.
304 * The destination addresses point to the locations where the
305 * VSP starts writing to memory, which can be any corner of the
306 * image depending on the combination of flipping and rotation.
307 */
308
309 /*
310 * First take the partition left coordinate into account.
311 * Compute the offset to order the partitions correctly on the
312 * output based on whether flipping is enabled. Consider
313 * horizontal flipping when rotation is disabled but vertical
314 * flipping when rotation is enabled, as rotating the image
315 * switches the horizontal and vertical directions. The offset
316 * is applied horizontally or vertically accordingly.
317 */
318 if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate)
319 offset = format->width - pipe->partition->wpf.left
320 - pipe->partition->wpf.width;
321 else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate)
322 offset = format->height - pipe->partition->wpf.left
323 - pipe->partition->wpf.width;
324 else
325 offset = pipe->partition->wpf.left;
326
327 for (i = 0; i < format->num_planes; ++i) {
328 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;
329 unsigned int vsub = i > 0 ? fmtinfo->vsub : 1;
330
331 if (wpf->flip.rotate)
332 mem.addr[i] += offset / vsub
333 * format->plane_fmt[i].bytesperline;
334 else
335 mem.addr[i] += offset / hsub
336 * fmtinfo->bpp[i] / 8;
337 }
338
339 if (flip & BIT(WPF_CTRL_VFLIP)) {
340 /*
341 * When rotating the output (after rotation) image
342 * height is equal to the partition width (before
343 * rotation). Otherwise it is equal to the output
344 * image height.
345 */
346 if (wpf->flip.rotate)
347 height = pipe->partition->wpf.width;
348 else
349 height = format->height;
350
351 mem.addr[0] += (height - 1)
352 * format->plane_fmt[0].bytesperline;
353
354 if (format->num_planes > 1) {
355 offset = (height / fmtinfo->vsub - 1)
356 * format->plane_fmt[1].bytesperline;
357 mem.addr[1] += offset;
358 mem.addr[2] += offset;
359 }
360 }
361
362 if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) {
363 unsigned int hoffset = max(0, (int)format->width - 16);
364
365 /*
366 * Compute the output coordinate. The partition
367 * horizontal (left) offset becomes a vertical offset.
368 */
369 for (i = 0; i < format->num_planes; ++i) {
370 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;
371
372 mem.addr[i] += hoffset / hsub
373 * fmtinfo->bpp[i] / 8;
374 }
375 }
376
377 /*
378 * On Gen3 hardware the SPUVS bit has no effect on 3-planar
379 * formats. Swap the U and V planes manually in that case.
380 */
381 if (vsp1->info->gen == 3 && format->num_planes == 3 &&
382 fmtinfo->swap_uv)
383 swap(mem.addr[1], mem.addr[2]);
384
385 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]);
386 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]);
387 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]);
388 return;
389 }
390
391 /* Format */ 253 /* Format */
392 if (!pipe->lif) { 254 if (!pipe->lif) {
393 const struct v4l2_pix_format_mplane *format = &wpf->format; 255 const struct v4l2_pix_format_mplane *format = &wpf->format;
@@ -461,6 +323,160 @@ static void wpf_configure(struct vsp1_entity *entity,
461 VI6_WFP_IRQ_ENB_DFEE); 323 VI6_WFP_IRQ_ENB_DFEE);
462} 324}
463 325
326static void wpf_configure_frame(struct vsp1_entity *entity,
327 struct vsp1_pipeline *pipe,
328 struct vsp1_dl_list *dl)
329{
330 const unsigned int mask = BIT(WPF_CTRL_VFLIP)
331 | BIT(WPF_CTRL_HFLIP);
332 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
333 unsigned long flags;
334 u32 outfmt;
335
336 spin_lock_irqsave(&wpf->flip.lock, flags);
337 wpf->flip.active = (wpf->flip.active & ~mask)
338 | (wpf->flip.pending & mask);
339 spin_unlock_irqrestore(&wpf->flip.lock, flags);
340
341 outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt;
342
343 if (wpf->flip.active & BIT(WPF_CTRL_VFLIP))
344 outfmt |= VI6_WPF_OUTFMT_FLP;
345 if (wpf->flip.active & BIT(WPF_CTRL_HFLIP))
346 outfmt |= VI6_WPF_OUTFMT_HFLP;
347
348 vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt);
349}
350
351static void wpf_configure_partition(struct vsp1_entity *entity,
352 struct vsp1_pipeline *pipe,
353 struct vsp1_dl_list *dl)
354{
355 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
356 struct vsp1_device *vsp1 = wpf->entity.vsp1;
357 struct vsp1_rwpf_memory mem = wpf->mem;
358 const struct v4l2_mbus_framefmt *sink_format;
359 const struct v4l2_pix_format_mplane *format = &wpf->format;
360 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
361 unsigned int width;
362 unsigned int height;
363 unsigned int offset;
364 unsigned int flip;
365 unsigned int i;
366
367 sink_format = vsp1_entity_get_pad_format(&wpf->entity,
368 wpf->entity.config,
369 RWPF_PAD_SINK);
370 width = sink_format->width;
371 height = sink_format->height;
372
373 /*
374 * Cropping. The partition algorithm can split the image into
375 * multiple slices.
376 */
377 if (pipe->partitions > 1)
378 width = pipe->partition->wpf.width;
379
380 vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN |
381 (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
382 (width << VI6_WPF_SZCLIP_SIZE_SHIFT));
383 vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN |
384 (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
385 (height << VI6_WPF_SZCLIP_SIZE_SHIFT));
386
387 if (pipe->lif)
388 return;
389
390 /*
391 * Update the memory offsets based on flipping configuration.
392 * The destination addresses point to the locations where the
393 * VSP starts writing to memory, which can be any corner of the
394 * image depending on the combination of flipping and rotation.
395 */
396
397 /*
398 * First take the partition left coordinate into account.
399 * Compute the offset to order the partitions correctly on the
400 * output based on whether flipping is enabled. Consider
401 * horizontal flipping when rotation is disabled but vertical
402 * flipping when rotation is enabled, as rotating the image
403 * switches the horizontal and vertical directions. The offset
404 * is applied horizontally or vertically accordingly.
405 */
406 flip = wpf->flip.active;
407
408 if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate)
409 offset = format->width - pipe->partition->wpf.left
410 - pipe->partition->wpf.width;
411 else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate)
412 offset = format->height - pipe->partition->wpf.left
413 - pipe->partition->wpf.width;
414 else
415 offset = pipe->partition->wpf.left;
416
417 for (i = 0; i < format->num_planes; ++i) {
418 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;
419 unsigned int vsub = i > 0 ? fmtinfo->vsub : 1;
420
421 if (wpf->flip.rotate)
422 mem.addr[i] += offset / vsub
423 * format->plane_fmt[i].bytesperline;
424 else
425 mem.addr[i] += offset / hsub
426 * fmtinfo->bpp[i] / 8;
427 }
428
429 if (flip & BIT(WPF_CTRL_VFLIP)) {
430 /*
431 * When rotating the output (after rotation) image
432 * height is equal to the partition width (before
433 * rotation). Otherwise it is equal to the output
434 * image height.
435 */
436 if (wpf->flip.rotate)
437 height = pipe->partition->wpf.width;
438 else
439 height = format->height;
440
441 mem.addr[0] += (height - 1)
442 * format->plane_fmt[0].bytesperline;
443
444 if (format->num_planes > 1) {
445 offset = (height / fmtinfo->vsub - 1)
446 * format->plane_fmt[1].bytesperline;
447 mem.addr[1] += offset;
448 mem.addr[2] += offset;
449 }
450 }
451
452 if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) {
453 unsigned int hoffset = max(0, (int)format->width - 16);
454
455 /*
456 * Compute the output coordinate. The partition
457 * horizontal (left) offset becomes a vertical offset.
458 */
459 for (i = 0; i < format->num_planes; ++i) {
460 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;
461
462 mem.addr[i] += hoffset / hsub
463 * fmtinfo->bpp[i] / 8;
464 }
465 }
466
467 /*
468 * On Gen3 hardware the SPUVS bit has no effect on 3-planar
469 * formats. Swap the U and V planes manually in that case.
470 */
471 if (vsp1->info->gen == 3 && format->num_planes == 3 &&
472 fmtinfo->swap_uv)
473 swap(mem.addr[1], mem.addr[2]);
474
475 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]);
476 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]);
477 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]);
478}
479
464static unsigned int wpf_max_width(struct vsp1_entity *entity, 480static unsigned int wpf_max_width(struct vsp1_entity *entity,
465 struct vsp1_pipeline *pipe) 481 struct vsp1_pipeline *pipe)
466{ 482{
@@ -480,7 +496,9 @@ static void wpf_partition(struct vsp1_entity *entity,
480 496
481static const struct vsp1_entity_operations wpf_entity_ops = { 497static const struct vsp1_entity_operations wpf_entity_ops = {
482 .destroy = vsp1_wpf_destroy, 498 .destroy = vsp1_wpf_destroy,
483 .configure = wpf_configure, 499 .configure_stream = wpf_configure_stream,
500 .configure_frame = wpf_configure_frame,
501 .configure_partition = wpf_configure_partition,
484 .max_width = wpf_max_width, 502 .max_width = wpf_max_width,
485 .partition = wpf_partition, 503 .partition = wpf_partition,
486}; 504};