[media] v4l: vsp1: Replace .set_memory() with VSP1_ENTITY_PARAMS_PARTITION
The new VSP1_ENTITY_PARAMS_PARTITION configuration parameters type covers all registers that need to be configured for every partition. This prepares for support of image partitioning, and replaces the .set_memory() operation as the memory registers take different values for every partition. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
d21fbbb4e9
commit
8ddf378429
|
@ -237,6 +237,9 @@ static void clu_configure(struct vsp1_entity *entity,
|
|||
break;
|
||||
}
|
||||
|
||||
case VSP1_ENTITY_PARAMS_PARTITION:
|
||||
break;
|
||||
|
||||
case VSP1_ENTITY_PARAMS_RUNTIME:
|
||||
/* 2D mode can only be used with the YCbCr pixel encoding. */
|
||||
if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode)
|
||||
|
|
|
@ -496,14 +496,9 @@ void vsp1_du_atomic_flush(struct device *dev)
|
|||
VSP1_ENTITY_PARAMS_INIT);
|
||||
entity->ops->configure(entity, pipe, pipe->dl,
|
||||
VSP1_ENTITY_PARAMS_RUNTIME);
|
||||
entity->ops->configure(entity, pipe, pipe->dl,
|
||||
VSP1_ENTITY_PARAMS_PARTITION);
|
||||
}
|
||||
|
||||
/* The memory buffer address must be applied after configuring
|
||||
* the RPF to make sure the crop offset are computed.
|
||||
*/
|
||||
if (entity->type == VSP1_ENTITY_RPF)
|
||||
vsp1_rwpf_set_memory(to_rwpf(&entity->subdev),
|
||||
pipe->dl);
|
||||
}
|
||||
|
||||
vsp1_dl_list_commit(pipe->dl);
|
||||
|
|
|
@ -38,10 +38,12 @@ enum vsp1_entity_type {
|
|||
/*
|
||||
* enum vsp1_entity_params - Entity configuration parameters class
|
||||
* @VSP1_ENTITY_PARAMS_INIT - Initial parameters
|
||||
* @VSP1_ENTITY_PARAMS_PARTITION - Per-image partition parameters
|
||||
* @VSP1_ENTITY_PARAMS_RUNTIME - Runtime-configurable parameters
|
||||
*/
|
||||
enum vsp1_entity_params {
|
||||
VSP1_ENTITY_PARAMS_INIT,
|
||||
VSP1_ENTITY_PARAMS_PARTITION,
|
||||
VSP1_ENTITY_PARAMS_RUNTIME,
|
||||
};
|
||||
|
||||
|
@ -73,15 +75,11 @@ struct vsp1_route {
|
|||
/**
|
||||
* struct vsp1_entity_operations - Entity operations
|
||||
* @destroy: Destroy the entity.
|
||||
* @set_memory: Setup memory buffer access. This operation applies the settings
|
||||
* stored in the rwpf mem field to the display list. Valid for RPF
|
||||
* and WPF only.
|
||||
* @configure: Setup the hardware based on the entity state (pipeline, formats,
|
||||
* selection rectangles, ...)
|
||||
*/
|
||||
struct vsp1_entity_operations {
|
||||
void (*destroy)(struct vsp1_entity *);
|
||||
void (*set_memory)(struct vsp1_entity *, struct vsp1_dl_list *dl);
|
||||
void (*configure)(struct vsp1_entity *, struct vsp1_pipeline *,
|
||||
struct vsp1_dl_list *, enum vsp1_entity_params);
|
||||
};
|
||||
|
|
|
@ -202,6 +202,9 @@ static void lut_configure(struct vsp1_entity *entity,
|
|||
vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN);
|
||||
break;
|
||||
|
||||
case VSP1_ENTITY_PARAMS_PARTITION:
|
||||
break;
|
||||
|
||||
case VSP1_ENTITY_PARAMS_RUNTIME:
|
||||
spin_lock_irqsave(&lut->lock, flags);
|
||||
dlb = lut->lut;
|
||||
|
|
|
@ -46,18 +46,6 @@ static const struct v4l2_subdev_ops rpf_ops = {
|
|||
* VSP1 Entity Operations
|
||||
*/
|
||||
|
||||
static void rpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
|
||||
{
|
||||
struct vsp1_rwpf *rpf = entity_to_rwpf(entity);
|
||||
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y,
|
||||
rpf->mem.addr[0] + rpf->offsets[0]);
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0,
|
||||
rpf->mem.addr[1] + rpf->offsets[1]);
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1,
|
||||
rpf->mem.addr[2] + rpf->offsets[1]);
|
||||
}
|
||||
|
||||
static void rpf_configure(struct vsp1_entity *entity,
|
||||
struct vsp1_pipeline *pipe,
|
||||
struct vsp1_dl_list *dl,
|
||||
|
@ -68,7 +56,6 @@ static void rpf_configure(struct vsp1_entity *entity,
|
|||
const struct v4l2_pix_format_mplane *format = &rpf->format;
|
||||
const struct v4l2_mbus_framefmt *source_format;
|
||||
const struct v4l2_mbus_framefmt *sink_format;
|
||||
const struct v4l2_rect *crop;
|
||||
unsigned int left = 0;
|
||||
unsigned int top = 0;
|
||||
u32 pstride;
|
||||
|
@ -84,35 +71,51 @@ static void rpf_configure(struct vsp1_entity *entity,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Source size, stride and crop offsets.
|
||||
*
|
||||
* The crop offsets correspond to the location of the crop rectangle top
|
||||
* left corner in the plane buffer. Only two offsets are needed, as
|
||||
* planes 2 and 3 always have identical strides.
|
||||
*/
|
||||
crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config);
|
||||
if (params == VSP1_ENTITY_PARAMS_PARTITION) {
|
||||
const struct v4l2_rect *crop;
|
||||
unsigned int offsets[2];
|
||||
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE,
|
||||
(crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
|
||||
(crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE,
|
||||
(crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
|
||||
(crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
|
||||
/* Source size and crop offsets.
|
||||
*
|
||||
* The crop offsets correspond to the location of the crop
|
||||
* rectangle top left corner in the plane buffer. Only two
|
||||
* offsets are needed, as planes 2 and 3 always have identical
|
||||
* strides.
|
||||
*/
|
||||
crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config);
|
||||
|
||||
rpf->offsets[0] = crop->top * format->plane_fmt[0].bytesperline
|
||||
+ crop->left * fmtinfo->bpp[0] / 8;
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE,
|
||||
(crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
|
||||
(crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE,
|
||||
(crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
|
||||
(crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
|
||||
|
||||
offsets[0] = crop->top * format->plane_fmt[0].bytesperline
|
||||
+ crop->left * fmtinfo->bpp[0] / 8;
|
||||
|
||||
if (format->num_planes > 1)
|
||||
offsets[1] = crop->top * format->plane_fmt[1].bytesperline
|
||||
+ crop->left / fmtinfo->hsub
|
||||
* fmtinfo->bpp[1] / 8;
|
||||
else
|
||||
offsets[1] = 0;
|
||||
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y,
|
||||
rpf->mem.addr[0] + offsets[0]);
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0,
|
||||
rpf->mem.addr[1] + offsets[1]);
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1,
|
||||
rpf->mem.addr[2] + offsets[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stride */
|
||||
pstride = format->plane_fmt[0].bytesperline
|
||||
<< VI6_RPF_SRCM_PSTRIDE_Y_SHIFT;
|
||||
|
||||
if (format->num_planes > 1) {
|
||||
rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline
|
||||
+ crop->left / fmtinfo->hsub * fmtinfo->bpp[1]
|
||||
/ 8;
|
||||
if (format->num_planes > 1)
|
||||
pstride |= format->plane_fmt[1].bytesperline
|
||||
<< VI6_RPF_SRCM_PSTRIDE_C_SHIFT;
|
||||
} else {
|
||||
rpf->offsets[1] = 0;
|
||||
}
|
||||
|
||||
vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_PSTRIDE, pstride);
|
||||
|
||||
|
@ -217,7 +220,6 @@ static void rpf_configure(struct vsp1_entity *entity,
|
|||
}
|
||||
|
||||
static const struct vsp1_entity_operations rpf_entity_ops = {
|
||||
.set_memory = rpf_set_memory,
|
||||
.configure = rpf_configure,
|
||||
};
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ struct vsp1_rwpf {
|
|||
unsigned int active;
|
||||
} flip;
|
||||
|
||||
unsigned int offsets[2];
|
||||
struct vsp1_rwpf_memory mem;
|
||||
|
||||
struct vsp1_dl_manager *dlm;
|
||||
|
@ -86,17 +85,5 @@ extern const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops;
|
|||
|
||||
struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf,
|
||||
struct v4l2_subdev_pad_config *config);
|
||||
/**
|
||||
* vsp1_rwpf_set_memory - Configure DMA addresses for a [RW]PF
|
||||
* @rwpf: the [RW]PF instance
|
||||
* @dl: the display list
|
||||
*
|
||||
* This function applies the cached memory buffer address to the display list.
|
||||
*/
|
||||
static inline void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf,
|
||||
struct vsp1_dl_list *dl)
|
||||
{
|
||||
rwpf->entity.ops->set_memory(&rwpf->entity, dl);
|
||||
}
|
||||
|
||||
#endif /* __VSP1_RWPF_H__ */
|
||||
|
|
|
@ -245,29 +245,20 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
|
|||
|
||||
static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
|
||||
{
|
||||
struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
|
||||
struct vsp1_entity *entity;
|
||||
unsigned int i;
|
||||
|
||||
if (!pipe->dl)
|
||||
pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
|
||||
|
||||
list_for_each_entry(entity, &pipe->entities, list_pipe) {
|
||||
if (entity->ops->configure)
|
||||
if (entity->ops->configure) {
|
||||
entity->ops->configure(entity, pipe, pipe->dl,
|
||||
VSP1_ENTITY_PARAMS_RUNTIME);
|
||||
entity->ops->configure(entity, pipe, pipe->dl,
|
||||
VSP1_ENTITY_PARAMS_PARTITION);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < vsp1->info->rpf_count; ++i) {
|
||||
struct vsp1_rwpf *rwpf = pipe->inputs[i];
|
||||
|
||||
if (rwpf)
|
||||
vsp1_rwpf_set_memory(rwpf, pipe->dl);
|
||||
}
|
||||
|
||||
if (!pipe->lif)
|
||||
vsp1_rwpf_set_memory(pipe->output, pipe->dl);
|
||||
|
||||
vsp1_dl_list_commit(pipe->dl);
|
||||
pipe->dl = NULL;
|
||||
|
||||
|
|
|
@ -173,37 +173,6 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity)
|
|||
vsp1_dlm_destroy(wpf->dlm);
|
||||
}
|
||||
|
||||
static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
|
||||
{
|
||||
struct vsp1_rwpf *wpf = entity_to_rwpf(entity);
|
||||
const struct v4l2_pix_format_mplane *format = &wpf->format;
|
||||
struct vsp1_rwpf_memory mem = wpf->mem;
|
||||
unsigned int flip = wpf->flip.active;
|
||||
unsigned int offset;
|
||||
|
||||
/* 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 different corners of the image
|
||||
* depending on vertical flipping. Horizontal flipping is handled
|
||||
* through a line buffer and doesn't modify the start address.
|
||||
*/
|
||||
if (flip & BIT(WPF_CTRL_VFLIP)) {
|
||||
mem.addr[0] += (format->height - 1)
|
||||
* format->plane_fmt[0].bytesperline;
|
||||
|
||||
if (format->num_planes > 1) {
|
||||
offset = (format->height / wpf->fmtinfo->vsub - 1)
|
||||
* format->plane_fmt[1].bytesperline;
|
||||
mem.addr[1] += offset;
|
||||
mem.addr[2] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]);
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]);
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]);
|
||||
}
|
||||
|
||||
static void wpf_configure(struct vsp1_entity *entity,
|
||||
struct vsp1_pipeline *pipe,
|
||||
struct vsp1_dl_list *dl,
|
||||
|
@ -237,7 +206,6 @@ static void wpf_configure(struct vsp1_entity *entity,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Format */
|
||||
sink_format = vsp1_entity_get_pad_format(&wpf->entity,
|
||||
wpf->entity.config,
|
||||
RWPF_PAD_SINK);
|
||||
|
@ -245,13 +213,53 @@ static void wpf_configure(struct vsp1_entity *entity,
|
|||
wpf->entity.config,
|
||||
RWPF_PAD_SOURCE);
|
||||
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN |
|
||||
(0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
|
||||
(source_format->width << VI6_WPF_SZCLIP_SIZE_SHIFT));
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN |
|
||||
(0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
|
||||
(source_format->height << VI6_WPF_SZCLIP_SIZE_SHIFT));
|
||||
if (params == VSP1_ENTITY_PARAMS_PARTITION) {
|
||||
const struct v4l2_pix_format_mplane *format = &wpf->format;
|
||||
struct vsp1_rwpf_memory mem = wpf->mem;
|
||||
unsigned int flip = wpf->flip.active;
|
||||
unsigned int width = source_format->width;
|
||||
unsigned int height = source_format->height;
|
||||
unsigned int offset;
|
||||
|
||||
/* Cropping. The partition algorithm can split the image into
|
||||
* multiple slices.
|
||||
*/
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN |
|
||||
(0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
|
||||
(width << VI6_WPF_SZCLIP_SIZE_SHIFT));
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN |
|
||||
(0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
|
||||
(height << VI6_WPF_SZCLIP_SIZE_SHIFT));
|
||||
|
||||
if (pipe->lif)
|
||||
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 different corners
|
||||
* of the image depending on vertical flipping. Horizontal
|
||||
* flipping is handled through a line buffer and doesn't modify
|
||||
* the start address.
|
||||
*/
|
||||
if (flip & BIT(WPF_CTRL_VFLIP)) {
|
||||
mem.addr[0] += (format->height - 1)
|
||||
* format->plane_fmt[0].bytesperline;
|
||||
|
||||
if (format->num_planes > 1) {
|
||||
offset = (format->height / wpf->fmtinfo->vsub - 1)
|
||||
* format->plane_fmt[1].bytesperline;
|
||||
mem.addr[1] += offset;
|
||||
mem.addr[2] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]);
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]);
|
||||
vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Format */
|
||||
if (!pipe->lif) {
|
||||
const struct v4l2_pix_format_mplane *format = &wpf->format;
|
||||
const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
|
||||
|
@ -320,7 +328,6 @@ static void wpf_configure(struct vsp1_entity *entity,
|
|||
|
||||
static const struct vsp1_entity_operations wpf_entity_ops = {
|
||||
.destroy = vsp1_wpf_destroy,
|
||||
.set_memory = wpf_set_memory,
|
||||
.configure = wpf_configure,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue