Commit 8ddf3784 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[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: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent d21fbbb4
......@@ -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);
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));
if (params == VSP1_ENTITY_PARAMS_PARTITION) {
const struct v4l2_rect *crop;
unsigned int offsets[2];
/* 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);
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;
}
rpf->offsets[0] = crop->top * format->plane_fmt[0].bytesperline
+ crop->left * fmtinfo->bpp[0] / 8;
/* 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,
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment