Lines Matching +full:flip +full:- +full:horizontal

1 // SPDX-License-Identifier: GPL-2.0+
3 * vsp1_wpf.c -- R-Car VSP1 Write Pixel Formatter
5 * Copyright (C) 2013-2014 Renesas Electronics Corporation
12 #include <media/v4l2-subdev.h>
25 /* -----------------------------------------------------------------------------
32 vsp1_dl_body_write(dlb, reg + wpf->entity.index * VI6_WPF_OFFSET, data); in vsp1_wpf_write()
35 /* -----------------------------------------------------------------------------
46 struct vsp1_video *video = wpf->video; in vsp1_wpf_set_rotation()
57 if (rotate == wpf->flip.rotate) in vsp1_wpf_set_rotation()
61 mutex_lock(&video->lock); in vsp1_wpf_set_rotation()
63 if (vb2_is_busy(&video->queue)) { in vsp1_wpf_set_rotation()
64 ret = -EBUSY; in vsp1_wpf_set_rotation()
68 sink_format = vsp1_entity_get_pad_format(&wpf->entity, in vsp1_wpf_set_rotation()
69 wpf->entity.config, in vsp1_wpf_set_rotation()
71 source_format = vsp1_entity_get_pad_format(&wpf->entity, in vsp1_wpf_set_rotation()
72 wpf->entity.config, in vsp1_wpf_set_rotation()
75 mutex_lock(&wpf->entity.lock); in vsp1_wpf_set_rotation()
78 source_format->width = sink_format->height; in vsp1_wpf_set_rotation()
79 source_format->height = sink_format->width; in vsp1_wpf_set_rotation()
81 source_format->width = sink_format->width; in vsp1_wpf_set_rotation()
82 source_format->height = sink_format->height; in vsp1_wpf_set_rotation()
85 wpf->flip.rotate = rotate; in vsp1_wpf_set_rotation()
87 mutex_unlock(&wpf->entity.lock); in vsp1_wpf_set_rotation()
90 mutex_unlock(&video->lock); in vsp1_wpf_set_rotation()
97 container_of(ctrl->handler, struct vsp1_rwpf, ctrls); in vsp1_wpf_s_ctrl()
99 u32 flip = 0; in vsp1_wpf_s_ctrl() local
103 rotation = wpf->flip.ctrls.rotate ? wpf->flip.ctrls.rotate->val : 0; in vsp1_wpf_s_ctrl()
109 * Compute the flip value resulting from all three controls, with in vsp1_wpf_s_ctrl()
111 * result in the pending flip field for the next frame that will be in vsp1_wpf_s_ctrl()
114 if (wpf->flip.ctrls.vflip->val) in vsp1_wpf_s_ctrl()
115 flip |= BIT(WPF_CTRL_VFLIP); in vsp1_wpf_s_ctrl()
117 if (wpf->flip.ctrls.hflip && wpf->flip.ctrls.hflip->val) in vsp1_wpf_s_ctrl()
118 flip |= BIT(WPF_CTRL_HFLIP); in vsp1_wpf_s_ctrl()
121 flip ^= BIT(WPF_CTRL_VFLIP) | BIT(WPF_CTRL_HFLIP); in vsp1_wpf_s_ctrl()
123 spin_lock_irq(&wpf->flip.lock); in vsp1_wpf_s_ctrl()
124 wpf->flip.pending = flip; in vsp1_wpf_s_ctrl()
125 spin_unlock_irq(&wpf->flip.lock); in vsp1_wpf_s_ctrl()
136 struct vsp1_device *vsp1 = wpf->entity.vsp1; in wpf_init_controls()
139 spin_lock_init(&wpf->flip.lock); in wpf_init_controls()
141 if (wpf->entity.index != 0) { in wpf_init_controls()
146 * When horizontal flip is supported the WPF implements three in wpf_init_controls()
147 * controls (horizontal flip, vertical flip and rotation). in wpf_init_controls()
152 * When only vertical flip is supported the WPF implements a in wpf_init_controls()
153 * single control (vertical flip). in wpf_init_controls()
164 wpf->flip.ctrls.vflip = in wpf_init_controls()
165 v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops, in wpf_init_controls()
170 wpf->flip.ctrls.hflip = in wpf_init_controls()
171 v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops, in wpf_init_controls()
173 wpf->flip.ctrls.rotate = in wpf_init_controls()
174 v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops, in wpf_init_controls()
176 v4l2_ctrl_cluster(3, &wpf->flip.ctrls.vflip); in wpf_init_controls()
179 if (wpf->ctrls.error) { in wpf_init_controls()
180 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", in wpf_init_controls()
181 wpf->entity.index); in wpf_init_controls()
182 return wpf->ctrls.error; in wpf_init_controls()
188 /* -----------------------------------------------------------------------------
195 struct vsp1_device *vsp1 = wpf->entity.vsp1; in wpf_s_stream()
204 vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); in wpf_s_stream()
205 vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + in wpf_s_stream()
211 /* -----------------------------------------------------------------------------
224 /* -----------------------------------------------------------------------------
232 vsp1_dlm_destroy(wpf->dlm); in vsp1_wpf_destroy()
238 unsigned int index = wpf->entity.index; in wpf_configure_writeback_chain()
242 dl_next = vsp1_dl_list_get(wpf->dlm); in wpf_configure_writeback_chain()
244 dev_err(wpf->entity.vsp1->dev, in wpf_configure_writeback_chain()
246 return -ENOMEM; in wpf_configure_writeback_chain()
261 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_configure_stream()
262 struct vsp1_device *vsp1 = wpf->entity.vsp1; in wpf_configure_stream()
265 unsigned int index = wpf->entity.index; in wpf_configure_stream()
271 sink_format = vsp1_entity_get_pad_format(&wpf->entity, in wpf_configure_stream()
272 wpf->entity.config, in wpf_configure_stream()
274 source_format = vsp1_entity_get_pad_format(&wpf->entity, in wpf_configure_stream()
275 wpf->entity.config, in wpf_configure_stream()
279 if (!pipe->lif || wpf->writeback) { in wpf_configure_stream()
280 const struct v4l2_pix_format_mplane *format = &wpf->format; in wpf_configure_stream()
281 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; in wpf_configure_stream()
283 outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; in wpf_configure_stream()
285 if (wpf->flip.rotate) in wpf_configure_stream()
288 if (fmtinfo->alpha) in wpf_configure_stream()
290 if (fmtinfo->swap_yc) in wpf_configure_stream()
292 if (fmtinfo->swap_uv) in wpf_configure_stream()
297 format->plane_fmt[0].bytesperline); in wpf_configure_stream()
298 if (format->num_planes > 1) in wpf_configure_stream()
300 format->plane_fmt[1].bytesperline); in wpf_configure_stream()
302 vsp1_wpf_write(wpf, dlb, VI6_WPF_DSWAP, fmtinfo->swap); in wpf_configure_stream()
310 if (sink_format->code != source_format->code) in wpf_configure_stream()
313 wpf->outfmt = outfmt; in wpf_configure_stream()
321 * inputs as sub-layers and select the virtual RPF as the master in wpf_configure_stream()
324 for (i = 0; i < vsp1->info->rpf_count; ++i) { in wpf_configure_stream()
325 struct vsp1_rwpf *input = pipe->inputs[i]; in wpf_configure_stream()
330 srcrpf |= (!pipe->brx && pipe->num_inputs == 1) in wpf_configure_stream()
331 ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) in wpf_configure_stream()
332 : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); in wpf_configure_stream()
335 if (pipe->brx) in wpf_configure_stream()
336 srcrpf |= pipe->brx->type == VSP1_ENTITY_BRU in wpf_configure_stream()
349 * never set for memory-to-memory pipelines). Start by adding a chained in wpf_configure_stream()
355 if (wpf->writeback) { in wpf_configure_stream()
358 wpf->writeback = false; in wpf_configure_stream()
362 wpf->writeback ? VI6_WPF_WRBCK_CTRL_WBMD : 0); in wpf_configure_stream()
372 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_configure_frame()
376 spin_lock_irqsave(&wpf->flip.lock, flags); in wpf_configure_frame()
377 wpf->flip.active = (wpf->flip.active & ~mask) in wpf_configure_frame()
378 | (wpf->flip.pending & mask); in wpf_configure_frame()
379 spin_unlock_irqrestore(&wpf->flip.lock, flags); in wpf_configure_frame()
381 outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt; in wpf_configure_frame()
383 if (wpf->flip.active & BIT(WPF_CTRL_VFLIP)) in wpf_configure_frame()
385 if (wpf->flip.active & BIT(WPF_CTRL_HFLIP)) in wpf_configure_frame()
396 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_configure_partition()
397 struct vsp1_device *vsp1 = wpf->entity.vsp1; in wpf_configure_partition()
398 struct vsp1_rwpf_memory mem = wpf->mem; in wpf_configure_partition()
400 const struct v4l2_pix_format_mplane *format = &wpf->format; in wpf_configure_partition()
401 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; in wpf_configure_partition()
406 unsigned int flip; in wpf_configure_partition() local
409 sink_format = vsp1_entity_get_pad_format(&wpf->entity, in wpf_configure_partition()
410 wpf->entity.config, in wpf_configure_partition()
412 width = sink_format->width; in wpf_configure_partition()
413 height = sink_format->height; in wpf_configure_partition()
420 if (pipe->partitions > 1) { in wpf_configure_partition()
421 width = pipe->partition->wpf.width; in wpf_configure_partition()
422 left = pipe->partition->wpf.left; in wpf_configure_partition()
436 if (pipe->lif && !wpf->writeback) in wpf_configure_partition()
450 * horizontal flipping when rotation is disabled but vertical in wpf_configure_partition()
452 * switches the horizontal and vertical directions. The offset in wpf_configure_partition()
455 flip = wpf->flip.active; in wpf_configure_partition()
457 if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate) in wpf_configure_partition()
458 offset = format->width - left - width; in wpf_configure_partition()
459 else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate) in wpf_configure_partition()
460 offset = format->height - left - width; in wpf_configure_partition()
464 for (i = 0; i < format->num_planes; ++i) { in wpf_configure_partition()
465 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; in wpf_configure_partition()
466 unsigned int vsub = i > 0 ? fmtinfo->vsub : 1; in wpf_configure_partition()
468 if (wpf->flip.rotate) in wpf_configure_partition()
470 * format->plane_fmt[i].bytesperline; in wpf_configure_partition()
473 * fmtinfo->bpp[i] / 8; in wpf_configure_partition()
476 if (flip & BIT(WPF_CTRL_VFLIP)) { in wpf_configure_partition()
483 if (wpf->flip.rotate) in wpf_configure_partition()
486 height = format->height; in wpf_configure_partition()
488 mem.addr[0] += (height - 1) in wpf_configure_partition()
489 * format->plane_fmt[0].bytesperline; in wpf_configure_partition()
491 if (format->num_planes > 1) { in wpf_configure_partition()
492 offset = (height / fmtinfo->vsub - 1) in wpf_configure_partition()
493 * format->plane_fmt[1].bytesperline; in wpf_configure_partition()
499 if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) { in wpf_configure_partition()
500 unsigned int hoffset = max(0, (int)format->width - 16); in wpf_configure_partition()
504 * horizontal (left) offset becomes a vertical offset. in wpf_configure_partition()
506 for (i = 0; i < format->num_planes; ++i) { in wpf_configure_partition()
507 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; in wpf_configure_partition()
510 * fmtinfo->bpp[i] / 8; in wpf_configure_partition()
515 * On Gen3 hardware the SPUVS bit has no effect on 3-planar in wpf_configure_partition()
518 if (vsp1->info->gen == 3 && format->num_planes == 3 && in wpf_configure_partition()
519 fmtinfo->swap_uv) in wpf_configure_partition()
527 * Writeback operates in single-shot mode and lasts for a single frame, in wpf_configure_partition()
530 wpf->writeback = false; in wpf_configure_partition()
536 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_max_width()
538 return wpf->flip.rotate ? 256 : wpf->max_width; in wpf_max_width()
547 partition->wpf = *window; in wpf_partition()
559 /* -----------------------------------------------------------------------------
569 wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); in vsp1_wpf_create()
571 return ERR_PTR(-ENOMEM); in vsp1_wpf_create()
573 if (vsp1->info->gen == 2) { in vsp1_wpf_create()
574 wpf->max_width = WPF_GEN2_MAX_WIDTH; in vsp1_wpf_create()
575 wpf->max_height = WPF_GEN2_MAX_HEIGHT; in vsp1_wpf_create()
577 wpf->max_width = WPF_GEN3_MAX_WIDTH; in vsp1_wpf_create()
578 wpf->max_height = WPF_GEN3_MAX_HEIGHT; in vsp1_wpf_create()
581 wpf->entity.ops = &wpf_entity_ops; in vsp1_wpf_create()
582 wpf->entity.type = VSP1_ENTITY_WPF; in vsp1_wpf_create()
583 wpf->entity.index = index; in vsp1_wpf_create()
586 ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops, in vsp1_wpf_create()
592 wpf->dlm = vsp1_dlm_create(vsp1, index, 64); in vsp1_wpf_create()
593 if (!wpf->dlm) { in vsp1_wpf_create()
594 ret = -ENOMEM; in vsp1_wpf_create()
601 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", in vsp1_wpf_create()
606 v4l2_ctrl_handler_setup(&wpf->ctrls); in vsp1_wpf_create()
611 vsp1_entity_destroy(&wpf->entity); in vsp1_wpf_create()