aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/vsp1/vsp1_wpf.c
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 /drivers/media/platform/vsp1/vsp1_wpf.c
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>
Diffstat (limited to 'drivers/media/platform/vsp1/vsp1_wpf.c')
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c302
1 files changed, 160 insertions, 142 deletions
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};