/* * Only consider the 0°/180° from/to 90°/270° modifications, the rest * is taken care of by the flipping configuration.
*/
rotate = rotation == 90 || rotation == 270; if (rotate == wpf->flip.rotate) return 0;
/* Changing rotation isn't allowed when buffers are allocated. */
mutex_lock(&video->lock);
if (vb2_is_busy(&video->queue)) {
ret = -EBUSY; goto done;
}
/* Update the rotation. */
rotation = wpf->flip.ctrls.rotate ? wpf->flip.ctrls.rotate->val : 0;
ret = vsp1_wpf_set_rotation(wpf, rotation); if (ret < 0) return ret;
/* * Compute the flip value resulting from all three controls, with * rotation by 180° flipping the image in both directions. Store the * result in the pending flip field for the next frame that will be * processed.
*/ if (wpf->flip.ctrls.vflip->val)
flip |= BIT(WPF_CTRL_VFLIP);
if (wpf->flip.ctrls.hflip && wpf->flip.ctrls.hflip->val)
flip |= BIT(WPF_CTRL_HFLIP);
/* * Write to registers directly when stopping the stream as there will be * no pipeline run to apply the display list.
*/
vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET +
VI6_WPF_SRCRPF, 0);
}
/* * Format configuration. Skip for IIF (VSPX) or if the pipe doesn't * write to memory.
*/ if (!pipe->iif && (!pipe->lif || wpf->writeback)) { conststruct v4l2_pix_format_mplane *format = &wpf->format; conststruct vsp1_format_info *fmtinfo = wpf->fmtinfo;
if (wpf->flip.rotate)
outfmt |= VI6_WPF_OUTFMT_ROT;
if (fmtinfo->alpha)
outfmt |= VI6_WPF_OUTFMT_PXA; if (fmtinfo->swap_yc)
outfmt |= VI6_WPF_OUTFMT_SPYCS; if (fmtinfo->swap_uv)
outfmt |= VI6_WPF_OUTFMT_SPUVS;
/* Destination stride and byte swapping. */
vsp1_wpf_write(wpf, dlb, VI6_WPF_DSTM_STRIDE_Y,
format->plane_fmt[0].bytesperline); if (format->num_planes > 1)
vsp1_wpf_write(wpf, dlb, VI6_WPF_DSTM_STRIDE_C,
format->plane_fmt[1].bytesperline);
/* * Sources. If the pipeline has a single input and BRx is not used, * configure it as the master layer. Otherwise configure all * inputs as sub-layers and select the virtual RPF as the master * layer. For VSPX configure the enabled sources as masters.
*/ for (i = 0; i < vsp1->info->rpf_count; ++i) { struct vsp1_rwpf *input = pipe->inputs[i];
/* * Configure writeback for display pipelines (the wpf writeback flag is * never set for memory-to-memory pipelines). Start by adding a chained * display list to disable writeback after a single frame, and process * to enable writeback. If the display list allocation fails don't * enable writeback as we wouldn't be able to safely disable it, * resulting in possible memory corruption.
*/ if (wpf->writeback) {
ret = wpf_configure_writeback_chain(wpf, dl); if (ret < 0)
wpf->writeback = false;
}
/* * Cropping. The partition algorithm can split the image into multiple * slices.
*/
width = partition->wpf.width;
left = partition->wpf.left;
height = partition->wpf.height;
/* * For display pipelines without writeback enabled there's no memory * address to configure, return now.
*/ if (pipe->lif && !wpf->writeback) return;
/* * Update the memory offsets based on flipping configuration. * The destination addresses point to the locations where the * VSP starts writing to memory, which can be any corner of the * image depending on the combination of flipping and rotation.
*/
/* * First take the partition left coordinate into account. * Compute the offset to order the partitions correctly on the * output based on whether flipping is enabled. Consider * horizontal flipping when rotation is disabled but vertical * flipping when rotation is enabled, as rotating the image * switches the horizontal and vertical directions. The offset * is applied horizontally or vertically accordingly.
*/
flip = wpf->flip.active;
if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate)
offset = format->width - left - width; elseif (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate)
offset = format->height - left - width; else
offset = left;
for (i = 0; i < format->num_planes; ++i) { unsignedint hsub = i > 0 ? fmtinfo->hsub : 1; unsignedint vsub = i > 0 ? fmtinfo->vsub : 1;
if (flip & BIT(WPF_CTRL_VFLIP)) { /* * When rotating the output (after rotation) image * height is equal to the partition width (before * rotation). Otherwise it is equal to the output * image height.
*/ if (wpf->flip.rotate)
height = width; else
height = format->height;
/* * On Gen3+ hardware the SPUVS bit has no effect on 3-planar * formats. Swap the U and V planes manually in that case.
*/ if (vsp1->info->gen >= 3 && format->num_planes == 3 &&
fmtinfo->swap_uv)
swap(mem.addr[1], mem.addr[2]);
/* * Writeback operates in single-shot mode and lasts for a single frame, * reset the writeback flag to false for the next frame.
*/
wpf->writeback = false;
}
sprintf(name, "wpf.%u", index);
ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &vsp1_rwpf_subdev_ops,
MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER); if (ret < 0) return ERR_PTR(ret);
/* Initialize the display list manager. */
wpf->dlm = vsp1_dlm_create(vsp1, index, 64); if (!wpf->dlm) {
ret = -ENOMEM; goto error;
}
/* Initialize the control handler. */
ret = wpf_init_controls(wpf); if (ret < 0) {
dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
index); goto error;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.