diff options
author | Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> | 2018-05-18 16:42:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-05-25 19:03:16 -0400 |
commit | 46ce3639a579c29dc3166a9a66522f72f11f560c (patch) | |
tree | 13bb07c31eb5edde959931cf7ef23d5b2f6bd5bc | |
parent | 2d9445db0ee9d8695ab3dadb614829b70e43b61f (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.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_clu.c | 78 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_drm.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_entity.c | 24 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_entity.h | 39 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_hgo.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_hgt.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_hsit.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_lif.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_lut.c | 47 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_rpf.c | 168 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_sru.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_uds.c | 56 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_uif.c | 16 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_video.c | 28 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_wpf.c | 302 |
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 | ||
284 | static void brx_configure(struct vsp1_entity *entity, | 284 | static 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 | ||
402 | static const struct vsp1_entity_operations brx_entity_ops = { | 398 | static 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 | ||
172 | static void clu_configure(struct vsp1_entity *entity, | 172 | static 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 | |||
189 | static 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 | ||
233 | static const struct vsp1_entity_operations clu_entity_ops = { | 226 | static 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 | ||
72 | void 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 | |||
80 | void 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 | |||
88 | void 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 | */ | ||
46 | enum 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 | */ |
87 | struct vsp1_entity_operations { | 77 | struct 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 | ||
154 | void vsp1_entity_configure_stream(struct vsp1_entity *entity, | ||
155 | struct vsp1_pipeline *pipe, | ||
156 | struct vsp1_dl_list *dl); | ||
157 | |||
158 | void vsp1_entity_configure_frame(struct vsp1_entity *entity, | ||
159 | struct vsp1_pipeline *pipe, | ||
160 | struct vsp1_dl_list *dl); | ||
161 | |||
162 | void vsp1_entity_configure_partition(struct vsp1_entity *entity, | ||
163 | struct vsp1_pipeline *pipe, | ||
164 | struct vsp1_dl_list *dl); | ||
165 | |||
159 | struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad); | 166 | struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad); |
160 | 167 | ||
161 | int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, | 168 | int 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 | ||
132 | static void hgo_configure(struct vsp1_entity *entity, | 132 | static 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 | ||
176 | static const struct vsp1_entity_operations hgo_entity_ops = { | 172 | static 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 | ||
128 | static void hgt_configure(struct vsp1_entity *entity, | 128 | static 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 | ||
177 | static const struct vsp1_entity_operations hgt_entity_ops = { | 173 | static 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 | ||
130 | static void hsit_configure(struct vsp1_entity *entity, | 130 | static 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 | ||
146 | static const struct vsp1_entity_operations hsit_entity_ops = { | 142 | static 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 | ||
84 | static void lif_configure(struct vsp1_entity *entity, | 84 | static 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 | ||
125 | static const struct vsp1_entity_operations lif_entity_ops = { | 121 | static 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 | ||
148 | static void lut_configure(struct vsp1_entity *entity, | 148 | static 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: | 157 | static 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 | ||
189 | static const struct vsp1_entity_operations lut_entity_ops = { | 185 | static 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 | ||
45 | static void rpf_configure(struct vsp1_entity *entity, | 45 | static 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 | ||
171 | static 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 | |||
185 | static 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 | |||
246 | static void rpf_partition(struct vsp1_entity *entity, | 254 | static 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 | ||
255 | static const struct vsp1_entity_operations rpf_entity_ops = { | 263 | static 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 | ||
270 | static void sru_configure(struct vsp1_entity *entity, | 270 | static 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 | ||
349 | static const struct vsp1_entity_operations sru_entity_ops = { | 345 | static 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 | ||
258 | static void uds_configure(struct vsp1_entity *entity, | 258 | static 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 | ||
305 | static 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 | |||
327 | static unsigned int uds_max_width(struct vsp1_entity *entity, | 330 | static 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 | ||
382 | static const struct vsp1_entity_operations uds_entity_ops = { | 385 | static 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 | ||
192 | static void uif_configure(struct vsp1_entity *entity, | 192 | static 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 | ||
233 | static const struct vsp1_entity_operations uif_entity_ops = { | 225 | static 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 | ||
392 | static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) | 389 | static 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 | ||
235 | static void wpf_configure(struct vsp1_entity *entity, | 235 | static 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 | ||
326 | static 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 | |||
351 | static 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 | |||
464 | static unsigned int wpf_max_width(struct vsp1_entity *entity, | 480 | static 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 | ||
481 | static const struct vsp1_entity_operations wpf_entity_ops = { | 497 | static 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 | }; |