Lines Matching +full:flip +full:- +full:vertical
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 = v4l2_subdev_state_get_format(wpf->entity.state, in vsp1_wpf_set_rotation()
70 source_format = v4l2_subdev_state_get_format(wpf->entity.state, in vsp1_wpf_set_rotation()
73 mutex_lock(&wpf->entity.lock); in vsp1_wpf_set_rotation()
76 source_format->width = sink_format->height; in vsp1_wpf_set_rotation()
77 source_format->height = sink_format->width; in vsp1_wpf_set_rotation()
79 source_format->width = sink_format->width; in vsp1_wpf_set_rotation()
80 source_format->height = sink_format->height; in vsp1_wpf_set_rotation()
83 wpf->flip.rotate = rotate; in vsp1_wpf_set_rotation()
85 mutex_unlock(&wpf->entity.lock); in vsp1_wpf_set_rotation()
88 mutex_unlock(&video->lock); in vsp1_wpf_set_rotation()
95 container_of(ctrl->handler, struct vsp1_rwpf, ctrls); in vsp1_wpf_s_ctrl()
97 u32 flip = 0; in vsp1_wpf_s_ctrl() local
101 rotation = wpf->flip.ctrls.rotate ? wpf->flip.ctrls.rotate->val : 0; in vsp1_wpf_s_ctrl()
107 * Compute the flip value resulting from all three controls, with in vsp1_wpf_s_ctrl()
109 * result in the pending flip field for the next frame that will be in vsp1_wpf_s_ctrl()
112 if (wpf->flip.ctrls.vflip->val) in vsp1_wpf_s_ctrl()
113 flip |= BIT(WPF_CTRL_VFLIP); in vsp1_wpf_s_ctrl()
115 if (wpf->flip.ctrls.hflip && wpf->flip.ctrls.hflip->val) in vsp1_wpf_s_ctrl()
116 flip |= BIT(WPF_CTRL_HFLIP); in vsp1_wpf_s_ctrl()
119 flip ^= BIT(WPF_CTRL_VFLIP) | BIT(WPF_CTRL_HFLIP); in vsp1_wpf_s_ctrl()
121 spin_lock_irq(&wpf->flip.lock); in vsp1_wpf_s_ctrl()
122 wpf->flip.pending = flip; in vsp1_wpf_s_ctrl()
123 spin_unlock_irq(&wpf->flip.lock); in vsp1_wpf_s_ctrl()
134 struct vsp1_device *vsp1 = wpf->entity.vsp1; in wpf_init_controls()
137 spin_lock_init(&wpf->flip.lock); in wpf_init_controls()
139 if (wpf->entity.index != 0) { in wpf_init_controls()
144 * When horizontal flip is supported the WPF implements three in wpf_init_controls()
145 * controls (horizontal flip, vertical flip and rotation). in wpf_init_controls()
150 * When only vertical flip is supported the WPF implements a in wpf_init_controls()
151 * single control (vertical flip). in wpf_init_controls()
162 wpf->flip.ctrls.vflip = in wpf_init_controls()
163 v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops, in wpf_init_controls()
168 wpf->flip.ctrls.hflip = in wpf_init_controls()
169 v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops, in wpf_init_controls()
171 wpf->flip.ctrls.rotate = in wpf_init_controls()
172 v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops, in wpf_init_controls()
174 v4l2_ctrl_cluster(3, &wpf->flip.ctrls.vflip); in wpf_init_controls()
177 if (wpf->ctrls.error) { in wpf_init_controls()
178 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", in wpf_init_controls()
179 wpf->entity.index); in wpf_init_controls()
180 return wpf->ctrls.error; in wpf_init_controls()
186 /* -----------------------------------------------------------------------------
192 struct vsp1_device *vsp1 = wpf->entity.vsp1; in vsp1_wpf_stop()
198 vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); in vsp1_wpf_stop()
199 vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + in vsp1_wpf_stop()
207 vsp1_dlm_destroy(wpf->dlm); in vsp1_wpf_destroy()
213 unsigned int index = wpf->entity.index; in wpf_configure_writeback_chain()
217 dl_next = vsp1_dl_list_get(wpf->dlm); in wpf_configure_writeback_chain()
219 dev_err(wpf->entity.vsp1->dev, in wpf_configure_writeback_chain()
221 return -ENOMEM; in wpf_configure_writeback_chain()
237 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_configure_stream()
238 struct vsp1_device *vsp1 = wpf->entity.vsp1; in wpf_configure_stream()
241 unsigned int index = wpf->entity.index; in wpf_configure_stream()
251 if (!pipe->lif || wpf->writeback) { in wpf_configure_stream()
252 const struct v4l2_pix_format_mplane *format = &wpf->format; in wpf_configure_stream()
253 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; in wpf_configure_stream()
255 outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; in wpf_configure_stream()
257 if (wpf->flip.rotate) in wpf_configure_stream()
260 if (fmtinfo->alpha) in wpf_configure_stream()
262 if (fmtinfo->swap_yc) in wpf_configure_stream()
264 if (fmtinfo->swap_uv) in wpf_configure_stream()
269 format->plane_fmt[0].bytesperline); in wpf_configure_stream()
270 if (format->num_planes > 1) in wpf_configure_stream()
272 format->plane_fmt[1].bytesperline); in wpf_configure_stream()
274 vsp1_wpf_write(wpf, dlb, VI6_WPF_DSWAP, fmtinfo->swap); in wpf_configure_stream()
282 if (sink_format->code != source_format->code) in wpf_configure_stream()
285 wpf->outfmt = outfmt; in wpf_configure_stream()
293 * inputs as sub-layers and select the virtual RPF as the master in wpf_configure_stream()
296 for (i = 0; i < vsp1->info->rpf_count; ++i) { in wpf_configure_stream()
297 struct vsp1_rwpf *input = pipe->inputs[i]; in wpf_configure_stream()
302 srcrpf |= (!pipe->brx && pipe->num_inputs == 1) in wpf_configure_stream()
303 ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) in wpf_configure_stream()
304 : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); in wpf_configure_stream()
307 if (pipe->brx) in wpf_configure_stream()
308 srcrpf |= pipe->brx->type == VSP1_ENTITY_BRU in wpf_configure_stream()
321 * never set for memory-to-memory pipelines). Start by adding a chained in wpf_configure_stream()
327 if (wpf->writeback) { in wpf_configure_stream()
330 wpf->writeback = false; in wpf_configure_stream()
334 wpf->writeback ? VI6_WPF_WRBCK_CTRL_WBMD : 0); in wpf_configure_stream()
344 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_configure_frame()
348 spin_lock_irqsave(&wpf->flip.lock, flags); in wpf_configure_frame()
349 wpf->flip.active = (wpf->flip.active & ~mask) in wpf_configure_frame()
350 | (wpf->flip.pending & mask); in wpf_configure_frame()
351 spin_unlock_irqrestore(&wpf->flip.lock, flags); in wpf_configure_frame()
353 outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt; in wpf_configure_frame()
355 if (wpf->flip.active & BIT(WPF_CTRL_VFLIP)) in wpf_configure_frame()
357 if (wpf->flip.active & BIT(WPF_CTRL_HFLIP)) in wpf_configure_frame()
369 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_configure_partition()
370 struct vsp1_device *vsp1 = wpf->entity.vsp1; in wpf_configure_partition()
371 struct vsp1_rwpf_memory mem = wpf->mem; in wpf_configure_partition()
372 const struct v4l2_pix_format_mplane *format = &wpf->format; in wpf_configure_partition()
373 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; in wpf_configure_partition()
378 unsigned int flip; in wpf_configure_partition() local
385 width = partition->wpf.width; in wpf_configure_partition()
386 left = partition->wpf.left; in wpf_configure_partition()
387 height = partition->wpf.height; in wpf_configure_partition()
400 if (pipe->lif && !wpf->writeback) in wpf_configure_partition()
414 * horizontal flipping when rotation is disabled but vertical in wpf_configure_partition()
416 * switches the horizontal and vertical directions. The offset in wpf_configure_partition()
419 flip = wpf->flip.active; in wpf_configure_partition()
421 if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate) in wpf_configure_partition()
422 offset = format->width - left - width; in wpf_configure_partition()
423 else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate) in wpf_configure_partition()
424 offset = format->height - left - width; in wpf_configure_partition()
428 for (i = 0; i < format->num_planes; ++i) { in wpf_configure_partition()
429 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; in wpf_configure_partition()
430 unsigned int vsub = i > 0 ? fmtinfo->vsub : 1; in wpf_configure_partition()
432 if (wpf->flip.rotate) in wpf_configure_partition()
434 * format->plane_fmt[i].bytesperline; in wpf_configure_partition()
437 * fmtinfo->bpp[i] / 8; in wpf_configure_partition()
440 if (flip & BIT(WPF_CTRL_VFLIP)) { in wpf_configure_partition()
447 if (wpf->flip.rotate) in wpf_configure_partition()
450 height = format->height; in wpf_configure_partition()
452 mem.addr[0] += (height - 1) in wpf_configure_partition()
453 * format->plane_fmt[0].bytesperline; in wpf_configure_partition()
455 if (format->num_planes > 1) { in wpf_configure_partition()
456 offset = (height / fmtinfo->vsub - 1) in wpf_configure_partition()
457 * format->plane_fmt[1].bytesperline; in wpf_configure_partition()
463 if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) { in wpf_configure_partition()
464 unsigned int hoffset = max(0, (int)format->width - 16); in wpf_configure_partition()
468 * horizontal (left) offset becomes a vertical offset. in wpf_configure_partition()
470 for (i = 0; i < format->num_planes; ++i) { in wpf_configure_partition()
471 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; in wpf_configure_partition()
474 * fmtinfo->bpp[i] / 8; in wpf_configure_partition()
479 * On Gen3+ hardware the SPUVS bit has no effect on 3-planar in wpf_configure_partition()
482 if (vsp1->info->gen >= 3 && format->num_planes == 3 && in wpf_configure_partition()
483 fmtinfo->swap_uv) in wpf_configure_partition()
491 * Writeback operates in single-shot mode and lasts for a single frame, in wpf_configure_partition()
494 wpf->writeback = false; in wpf_configure_partition()
501 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); in wpf_max_width()
503 return wpf->flip.rotate ? 256 : wpf->max_width; in wpf_max_width()
513 partition->wpf = *window; in wpf_partition()
525 /* -----------------------------------------------------------------------------
535 wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); in vsp1_wpf_create()
537 return ERR_PTR(-ENOMEM); in vsp1_wpf_create()
539 if (vsp1->info->gen == 2) { in vsp1_wpf_create()
540 wpf->max_width = WPF_GEN2_MAX_WIDTH; in vsp1_wpf_create()
541 wpf->max_height = WPF_GEN2_MAX_HEIGHT; in vsp1_wpf_create()
543 wpf->max_width = WPF_GEN3_MAX_WIDTH; in vsp1_wpf_create()
544 wpf->max_height = WPF_GEN3_MAX_HEIGHT; in vsp1_wpf_create()
547 wpf->entity.ops = &wpf_entity_ops; in vsp1_wpf_create()
548 wpf->entity.type = VSP1_ENTITY_WPF; in vsp1_wpf_create()
549 wpf->entity.index = index; in vsp1_wpf_create()
552 ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &vsp1_rwpf_subdev_ops, in vsp1_wpf_create()
558 wpf->dlm = vsp1_dlm_create(vsp1, index, 64); in vsp1_wpf_create()
559 if (!wpf->dlm) { in vsp1_wpf_create()
560 ret = -ENOMEM; in vsp1_wpf_create()
567 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", in vsp1_wpf_create()
572 v4l2_ctrl_handler_setup(&wpf->ctrls); in vsp1_wpf_create()
577 vsp1_entity_destroy(&wpf->entity); in vsp1_wpf_create()