From 437c24dd19b88898557c51c23c84122f236c9371 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Wed, 5 Oct 2016 11:41:00 +0100 Subject: Revert "[media] v4l: vsp1: Supply frames to the DU continuously" This reverts commit 3299ba5c0b21 ("[media] v4l: vsp1: Supply frames to the DU continuously") The DU output mode does not rely on frames being supplied on the WPF as its pipeline is supplied from DRM. For the upcoming WPF writeback functionality, we will choose to enable writeback mode if there is an output buffer, or disable it (leaving the existing display pipeline unharmed) otherwise. Signed-off-by: Kieran Bingham Signed-off-by: Laurent Pinchart Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 7ceaf3222145..328d686189be 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -307,11 +307,6 @@ static int vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe) * This function completes the current buffer by filling its sequence number, * time stamp and payload size, and hands it back to the videobuf core. * - * When operating in DU output mode (deep pipeline to the DU through the LIF), - * the VSP1 needs to constantly supply frames to the display. In that case, if - * no other buffer is queued, reuse the one that has just been processed instead - * of handing it back to the videobuf core. - * * Return the next queued buffer or NULL if the queue is empty. */ static struct vsp1_vb2_buffer * @@ -333,12 +328,6 @@ vsp1_video_complete_buffer(struct vsp1_video *video) done = list_first_entry(&video->irqqueue, struct vsp1_vb2_buffer, queue); - /* In DU output mode reuse the buffer if the list is singular. */ - if (pipe->lif && list_is_singular(&video->irqqueue)) { - spin_unlock_irqrestore(&video->irqlock, flags); - return done; - } - list_del(&done->queue); if (!list_empty(&video->irqqueue)) -- cgit v1.2.3 From 79b15b4b82013d73e8702d65470419ecbfc7a7b5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 20 Sep 2018 17:54:56 +0100 Subject: media: vsp1: wpf: Fix partition configuration for display pipelines When configuring partitions for memory-to-memory pipelines, the WPF accesses data of the current partition through pipe->partition. Writeback support will require full configuration of the WPF while not providing a valid pipe->partition. Rework the configuration code to fall back to the full image width in that case, as is already done for the part of the configuration currently relevant for display pipelines. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_wpf.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 32bb207b2007..a07c5944b598 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -362,6 +362,7 @@ static void wpf_configure_partition(struct vsp1_entity *entity, const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; unsigned int width; unsigned int height; + unsigned int left; unsigned int offset; unsigned int flip; unsigned int i; @@ -371,13 +372,16 @@ static void wpf_configure_partition(struct vsp1_entity *entity, RWPF_PAD_SINK); width = sink_format->width; height = sink_format->height; + left = 0; /* * Cropping. The partition algorithm can split the image into * multiple slices. */ - if (pipe->partitions > 1) + if (pipe->partitions > 1) { width = pipe->partition->wpf.width; + left = pipe->partition->wpf.left; + } vsp1_wpf_write(wpf, dlb, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | (0 << VI6_WPF_SZCLIP_OFST_SHIFT) | @@ -408,13 +412,11 @@ static void wpf_configure_partition(struct vsp1_entity *entity, flip = wpf->flip.active; if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate) - offset = format->width - pipe->partition->wpf.left - - pipe->partition->wpf.width; + offset = format->width - left - width; else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate) - offset = format->height - pipe->partition->wpf.left - - pipe->partition->wpf.width; + offset = format->height - left - width; else - offset = pipe->partition->wpf.left; + offset = left; for (i = 0; i < format->num_planes; ++i) { unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; @@ -436,7 +438,7 @@ static void wpf_configure_partition(struct vsp1_entity *entity, * image height. */ if (wpf->flip.rotate) - height = pipe->partition->wpf.width; + height = width; else height = format->height; -- cgit v1.2.3 From 08af8538d4cecdb22ff56c48c522875c8a9f5541 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 16 Feb 2019 03:24:05 +0200 Subject: media: vsp1: Replace leftover occurrence of fragment with body Display list fragments have been renamed to bodies. Replace one last occurrence of the word fragment in the documentation. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 26289adaf658..64af449791b0 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -699,8 +699,8 @@ struct vsp1_dl_body *vsp1_dl_list_get_body0(struct vsp1_dl_list *dl) * which bodies are added. * * Adding a body to a display list passes ownership of the body to the list. The - * caller retains its reference to the fragment when adding it to the display - * list, but is not allowed to add new entries to the body. + * caller retains its reference to the body when adding it to the display list, + * but is not allowed to add new entries to the body. * * The reference must be explicitly released by a call to vsp1_dl_body_put() * when the body isn't needed anymore. -- cgit v1.2.3 From ae444200042ac6816539bfa5242ff821c3abff8e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 16 Feb 2019 03:27:43 +0200 Subject: media: vsp1: Fix addresses of display-related registers for VSP-DL The VSP-DL instances have two LIFs, and thus two copies of the VI6_DISP_IRQ_ENB, VI6_DISP_IRQ_STA and VI6_WPF_WRBCK_CTRL registers. Fix the corresponding macros accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 4 ++-- drivers/media/platform/vsp1/vsp1_regs.h | 6 +++--- drivers/media/platform/vsp1/vsp1_wpf.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 84895385d2e5..f5e810ca1f13 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -700,8 +700,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index, drm_pipe->du_private = cfg->callback_data; /* Disable the display interrupts. */ - vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0); - vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0); + vsp1_write(vsp1, VI6_DISP_IRQ_STA(pipe_index), 0); + vsp1_write(vsp1, VI6_DISP_IRQ_ENB(pipe_index), 0); /* Configure all entities in the pipeline. */ vsp1_du_pipeline_configure(pipe); diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index f6e4157095cc..1bb1d39c60d9 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -39,12 +39,12 @@ #define VI6_WFP_IRQ_STA_DFE (1 << 1) #define VI6_WFP_IRQ_STA_FRE (1 << 0) -#define VI6_DISP_IRQ_ENB 0x0078 +#define VI6_DISP_IRQ_ENB(n) (0x0078 + (n) * 60) #define VI6_DISP_IRQ_ENB_DSTE (1 << 8) #define VI6_DISP_IRQ_ENB_MAEE (1 << 5) #define VI6_DISP_IRQ_ENB_LNEE(n) (1 << (n)) -#define VI6_DISP_IRQ_STA 0x007c +#define VI6_DISP_IRQ_STA(n) (0x007c + (n) * 60) #define VI6_DISP_IRQ_STA_DST (1 << 8) #define VI6_DISP_IRQ_STA_MAE (1 << 5) #define VI6_DISP_IRQ_STA_LNE(n) (1 << (n)) @@ -307,7 +307,7 @@ #define VI6_WPF_DSTM_ADDR_C0 0x1028 #define VI6_WPF_DSTM_ADDR_C1 0x102c -#define VI6_WPF_WRBCK_CTRL 0x1034 +#define VI6_WPF_WRBCK_CTRL(n) (0x1034 + (n) * 0x100) #define VI6_WPF_WRBCK_CTRL_WBMD (1 << 0) /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index a07c5944b598..18c49e3a7875 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -291,7 +291,7 @@ static void wpf_configure_stream(struct vsp1_entity *entity, vsp1_dl_body_write(dlb, VI6_DPR_WPF_FPORCH(wpf->entity.index), VI6_DPR_WPF_FPORCH_FP_WPFN); - vsp1_dl_body_write(dlb, VI6_WPF_WRBCK_CTRL, 0); + vsp1_dl_body_write(dlb, VI6_WPF_WRBCK_CTRL(wpf->entity.index), 0); /* * Sources. If the pipeline has a single input and BRx is not used, -- cgit v1.2.3 From 65cddb1976607400915ff1ac1b59a52b61cff0a0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 16 Feb 2019 03:34:59 +0200 Subject: media: vsp1: Replace the display list internal flag with a flags field To prepare for addition of more flags to the display list, replace the 'internal' flag field by a bitmask 'flags' field. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 31 +++++++++++++++++-------------- drivers/media/platform/vsp1/vsp1_dl.h | 2 +- drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++++-- drivers/media/platform/vsp1/vsp1_video.c | 2 +- 4 files changed, 25 insertions(+), 18 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 64af449791b0..886b3a69d329 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -178,7 +178,7 @@ struct vsp1_dl_cmd_pool { * @post_cmd: post command to be issued through extended dl header * @has_chain: if true, indicates that there's a partition chain * @chain: entry in the display list partition chain - * @internal: whether the display list is used for internal purpose + * @flags: display list flags, a combination of VSP1_DL_FRAME_END_* */ struct vsp1_dl_list { struct list_head list; @@ -197,7 +197,7 @@ struct vsp1_dl_list { bool has_chain; struct list_head chain; - bool internal; + unsigned int flags; }; /** @@ -861,13 +861,15 @@ static void vsp1_dl_list_commit_continuous(struct vsp1_dl_list *dl) * * If a display list is already pending we simply drop it as the new * display list is assumed to contain a more recent configuration. It is - * an error if the already pending list has the internal flag set, as - * there is then a process waiting for that list to complete. This - * shouldn't happen as the waiting process should perform proper - * locking, but warn just in case. + * an error if the already pending list has the + * VSP1_DL_FRAME_END_INTERNAL flag set, as there is then a process + * waiting for that list to complete. This shouldn't happen as the + * waiting process should perform proper locking, but warn just in + * case. */ if (vsp1_dl_list_hw_update_pending(dlm)) { - WARN_ON(dlm->pending && dlm->pending->internal); + WARN_ON(dlm->pending && + (dlm->pending->flags & VSP1_DL_FRAME_END_INTERNAL)); __vsp1_dl_list_put(dlm->pending); dlm->pending = dl; return; @@ -897,7 +899,7 @@ static void vsp1_dl_list_commit_singleshot(struct vsp1_dl_list *dl) dlm->active = dl; } -void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool internal) +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, unsigned int dl_flags) { struct vsp1_dl_manager *dlm = dl->dlm; struct vsp1_dl_list *dl_next; @@ -912,7 +914,7 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool internal) vsp1_dl_list_fill_header(dl_next, last); } - dl->internal = internal; + dl->flags = dl_flags & ~VSP1_DL_FRAME_END_COMPLETED; spin_lock_irqsave(&dlm->lock, flags); @@ -941,9 +943,10 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool internal) * set in single-shot mode as display list processing is then not continuous and * races never occur. * - * The VSP1_DL_FRAME_END_INTERNAL flag indicates that the previous display list - * has completed and had been queued with the internal notification flag. - * Internal notification is only supported for continuous mode. + * The following flags are only supported for continuous mode. + * + * The VSP1_DL_FRAME_END_INTERNAL flag indicates that the display list that just + * became active had been queued with the internal notification flag. */ unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) { @@ -986,9 +989,9 @@ unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) * frame end interrupt. The display list thus becomes active. */ if (dlm->queued) { - if (dlm->queued->internal) + if (dlm->queued->flags & VSP1_DL_FRAME_END_INTERNAL) flags |= VSP1_DL_FRAME_END_INTERNAL; - dlm->queued->internal = false; + dlm->queued->flags &= ~VSP1_DL_FRAME_END_INTERNAL; __vsp1_dl_list_put(dlm->active); dlm->active = dlm->queued; diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 125750dc8b5c..e0fdb145e6ed 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -61,7 +61,7 @@ struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm); void vsp1_dl_list_put(struct vsp1_dl_list *dl); struct vsp1_dl_body *vsp1_dl_list_get_body0(struct vsp1_dl_list *dl); struct vsp1_dl_ext_cmd *vsp1_dl_get_pre_cmd(struct vsp1_dl_list *dl); -void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool internal); +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, unsigned int dl_flags); struct vsp1_dl_body_pool * vsp1_dl_body_pool_create(struct vsp1_device *vsp1, unsigned int num_bodies, diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index f5e810ca1f13..e8f83d4b7a39 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -34,7 +34,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, unsigned int completion) { struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); - bool complete = completion == VSP1_DL_FRAME_END_COMPLETED; + bool complete = completion & VSP1_DL_FRAME_END_COMPLETED; if (drm_pipe->du_complete) { struct vsp1_entity *uif = drm_pipe->uif; @@ -537,6 +537,10 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) struct vsp1_entity *next; struct vsp1_dl_list *dl; struct vsp1_dl_body *dlb; + unsigned int dl_flags = 0; + + if (drm_pipe->force_brx_release) + dl_flags |= VSP1_DL_FRAME_END_INTERNAL; dl = vsp1_dl_list_get(pipe->output->dlm); dlb = vsp1_dl_list_get_body0(dl); @@ -559,7 +563,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) vsp1_entity_configure_partition(entity, pipe, dl, dlb); } - vsp1_dl_list_commit(dl, drm_pipe->force_brx_release); + vsp1_dl_list_commit(dl, dl_flags); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 328d686189be..9ae20982604a 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -421,7 +421,7 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) } /* Complete, and commit the head display list. */ - vsp1_dl_list_commit(dl, false); + vsp1_dl_list_commit(dl, 0); pipe->configured = true; vsp1_pipeline_run(pipe); -- cgit v1.2.3 From b36c6049ed4b6ef73fd2ca3802335af921886f91 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 11 Mar 2019 20:13:43 +0200 Subject: media: vsp1: Add vsp1_dl_list argument to .configure_stream() operation The WPF needs access to the current display list to configure writeback. Add a display list pointer to the VSP1 entity .configure_stream() operation. Only display pipelines can make use of the display list there as mem-to-mem pipelines don't have access to a display list at stream configuration time. This is not an issue as writeback is only used for display pipelines. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_brx.c | 1 + drivers/media/platform/vsp1/vsp1_clu.c | 1 + drivers/media/platform/vsp1/vsp1_drm.c | 2 +- drivers/media/platform/vsp1/vsp1_entity.c | 3 ++- drivers/media/platform/vsp1/vsp1_entity.h | 7 +++++-- drivers/media/platform/vsp1/vsp1_hgo.c | 1 + drivers/media/platform/vsp1/vsp1_hgt.c | 1 + drivers/media/platform/vsp1/vsp1_hsit.c | 1 + drivers/media/platform/vsp1/vsp1_lif.c | 1 + drivers/media/platform/vsp1/vsp1_lut.c | 1 + drivers/media/platform/vsp1/vsp1_rpf.c | 1 + drivers/media/platform/vsp1/vsp1_sru.c | 1 + drivers/media/platform/vsp1/vsp1_uds.c | 1 + drivers/media/platform/vsp1/vsp1_uif.c | 1 + drivers/media/platform/vsp1/vsp1_video.c | 3 ++- drivers/media/platform/vsp1/vsp1_wpf.c | 1 + 16 files changed, 22 insertions(+), 5 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c index 58ad248cd7f7..2d86c718a5cf 100644 --- a/drivers/media/platform/vsp1/vsp1_brx.c +++ b/drivers/media/platform/vsp1/vsp1_brx.c @@ -283,6 +283,7 @@ static const struct v4l2_subdev_ops brx_ops = { static void brx_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_brx *brx = to_brx(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index 942fc14c19d1..a47b23bf5abf 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -171,6 +171,7 @@ static const struct v4l2_subdev_ops clu_ops = { static void clu_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_clu *clu = to_clu(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index e8f83d4b7a39..e28a742a7575 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -558,7 +558,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) } vsp1_entity_route_setup(entity, pipe, dlb); - vsp1_entity_configure_stream(entity, pipe, dlb); + vsp1_entity_configure_stream(entity, pipe, dl, dlb); vsp1_entity_configure_frame(entity, pipe, dl, dlb); vsp1_entity_configure_partition(entity, pipe, dl, dlb); } diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index a54ab528b060..aa9d2286056e 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -71,10 +71,11 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity, void vsp1_entity_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { if (entity->ops->configure_stream) - entity->ops->configure_stream(entity, pipe, dlb); + entity->ops->configure_stream(entity, pipe, dl, dlb); } void vsp1_entity_configure_frame(struct vsp1_entity *entity, diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 97acb7795cf1..a1ceb37bb837 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -67,7 +67,9 @@ struct vsp1_route { * struct vsp1_entity_operations - Entity operations * @destroy: Destroy the entity. * @configure_stream: Setup the hardware parameters for the stream which do - * not vary between frames (pipeline, formats). + * not vary between frames (pipeline, formats). Note that + * the vsp1_dl_list argument is only valid for display + * pipeline and will be NULL for mem-to-mem pipelines. * @configure_frame: Configure the runtime parameters for each frame. * @configure_partition: Configure partition specific parameters. * @max_width: Return the max supported width of data that the entity can @@ -78,7 +80,7 @@ struct vsp1_route { struct vsp1_entity_operations { void (*destroy)(struct vsp1_entity *); void (*configure_stream)(struct vsp1_entity *, struct vsp1_pipeline *, - struct vsp1_dl_body *); + struct vsp1_dl_list *, struct vsp1_dl_body *); void (*configure_frame)(struct vsp1_entity *, struct vsp1_pipeline *, struct vsp1_dl_list *, struct vsp1_dl_body *); void (*configure_partition)(struct vsp1_entity *, @@ -155,6 +157,7 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity, void vsp1_entity_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb); void vsp1_entity_configure_frame(struct vsp1_entity *entity, diff --git a/drivers/media/platform/vsp1/vsp1_hgo.c b/drivers/media/platform/vsp1/vsp1_hgo.c index 827373c25351..bf3f981f93a1 100644 --- a/drivers/media/platform/vsp1/vsp1_hgo.c +++ b/drivers/media/platform/vsp1/vsp1_hgo.c @@ -131,6 +131,7 @@ static const struct v4l2_ctrl_config hgo_num_bins_control = { static void hgo_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_hgo *hgo = to_hgo(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_hgt.c b/drivers/media/platform/vsp1/vsp1_hgt.c index bb6ce6fdd5f4..aa1c718e0453 100644 --- a/drivers/media/platform/vsp1/vsp1_hgt.c +++ b/drivers/media/platform/vsp1/vsp1_hgt.c @@ -127,6 +127,7 @@ static const struct v4l2_ctrl_config hgt_hue_areas = { static void hgt_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_hgt *hgt = to_hgt(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 39ab2e0c7c18..d5ebd9d08c8a 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -129,6 +129,7 @@ static const struct v4l2_subdev_ops hsit_ops = { static void hsit_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_hsit *hsit = to_hsit(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 8b0a26335d70..14ed5d7bd061 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -84,6 +84,7 @@ static const struct v4l2_subdev_ops lif_ops = { static void lif_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { const struct v4l2_mbus_framefmt *format; diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 64c48d9459b0..9f88842d7048 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -147,6 +147,7 @@ static const struct v4l2_subdev_ops lut_ops = { static void lut_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_lut *lut = to_lut(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 616afa7e165f..85587c1b6a37 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -57,6 +57,7 @@ static const struct v4l2_subdev_ops rpf_ops = { static void rpf_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index b1617cb1f2b9..2b65457ee12f 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -269,6 +269,7 @@ static const struct v4l2_subdev_ops sru_ops = { static void sru_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { const struct vsp1_sru_param *param; diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 27012af973b2..5fc04c082d1a 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -257,6 +257,7 @@ static const struct v4l2_subdev_ops uds_ops = { static void uds_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_uds *uds = to_uds(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c index 4b58d51df231..467d1072577b 100644 --- a/drivers/media/platform/vsp1/vsp1_uif.c +++ b/drivers/media/platform/vsp1/vsp1_uif.c @@ -192,6 +192,7 @@ static const struct v4l2_subdev_ops uif_ops = { static void uif_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_uif *uif = to_uif(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 9ae20982604a..fd98e483b2f4 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -825,7 +825,8 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) list_for_each_entry(entity, &pipe->entities, list_pipe) { vsp1_entity_route_setup(entity, pipe, pipe->stream_config); - vsp1_entity_configure_stream(entity, pipe, pipe->stream_config); + vsp1_entity_configure_stream(entity, pipe, NULL, + pipe->stream_config); } return 0; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 18c49e3a7875..fc5c1b0f6633 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -234,6 +234,7 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity) static void wpf_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); -- cgit v1.2.3 From 5c7de45a43a8ac00e61f5551b3d639c95c038e4b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 11 Mar 2019 20:16:33 +0200 Subject: media: vsp1: dl: Allow chained display lists for display pipelines Refactor the display list header setup to allow chained display lists with display pipelines. Chain the display lists as for mem-to-mem pipelines, but enable the frame end interrupt for every list as display pipelines have a single list per frame. This feature will be used to disable writeback exactly one frame after enabling it by chaining a writeback disable display list. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 886b3a69d329..ed7cda4130f2 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -770,17 +770,35 @@ static void vsp1_dl_list_fill_header(struct vsp1_dl_list *dl, bool is_last) } dl->header->num_lists = num_lists; + dl->header->flags = 0; - if (!list_empty(&dl->chain) && !is_last) { + /* + * Enable the interrupt for the end of each frame. In continuous mode + * chained lists are used with one list per frame, so enable the + * interrupt for each list. In singleshot mode chained lists are used + * to partition a single frame, so enable the interrupt for the last + * list only. + */ + if (!dlm->singleshot || is_last) + dl->header->flags |= VSP1_DLH_INT_ENABLE; + + /* + * In continuous mode enable auto-start for all lists, as the VSP must + * loop on the same list until a new one is queued. In singleshot mode + * enable auto-start for all lists but the last to chain processing of + * partitions without software intervention. + */ + if (!dlm->singleshot || !is_last) + dl->header->flags |= VSP1_DLH_AUTO_START; + + if (!is_last) { /* - * If this display list's chain is not empty, we are on a list, - * and the next item is the display list that we must queue for - * automatic processing by the hardware. + * If this is not the last display list in the chain, queue the + * next item for automatic processing by the hardware. */ struct vsp1_dl_list *next = list_next_entry(dl, chain); dl->header->next_header = next->dma; - dl->header->flags = VSP1_DLH_AUTO_START; } else if (!dlm->singleshot) { /* * if the display list manager works in continuous mode, the VSP @@ -788,13 +806,6 @@ static void vsp1_dl_list_fill_header(struct vsp1_dl_list *dl, bool is_last) * instructed to do otherwise. */ dl->header->next_header = dl->dma; - dl->header->flags = VSP1_DLH_INT_ENABLE | VSP1_DLH_AUTO_START; - } else { - /* - * Otherwise, in mem-to-mem mode, we work in single-shot mode - * and the next display list must not be started automatically. - */ - dl->header->flags = VSP1_DLH_INT_ENABLE; } if (!dl->extension) -- cgit v1.2.3 From 9ec5742b6930fb6b4e95b1f249804bf4cb683f9c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 20 Feb 2019 18:01:57 +0200 Subject: media: vsp1: wpf: Add writeback support Add support for the writeback feature of the WPF, to enable capturing frames at the WPF output for display pipelines. To enable writeback the vsp1_rwpf structure mem field must be set to the address of the writeback buffer and the writeback field set to true before the WPF .configure_stream() and .configure_partition() are called. The WPF will enable writeback in the display list for a single frame, and writeback will then be automatically disabled. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rwpf.h | 1 + drivers/media/platform/vsp1/vsp1_wpf.c | 66 ++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 9 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 70742ecf766f..2f3582590618 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -61,6 +61,7 @@ struct vsp1_rwpf { } flip; struct vsp1_rwpf_memory mem; + bool writeback; struct vsp1_dl_manager *dlm; }; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index fc5c1b0f6633..208498fa6ed7 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -232,6 +232,27 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity) vsp1_dlm_destroy(wpf->dlm); } +static int wpf_configure_writeback_chain(struct vsp1_rwpf *wpf, + struct vsp1_dl_list *dl) +{ + unsigned int index = wpf->entity.index; + struct vsp1_dl_list *dl_next; + struct vsp1_dl_body *dlb; + + dl_next = vsp1_dl_list_get(wpf->dlm); + if (!dl_next) { + dev_err(wpf->entity.vsp1->dev, + "Failed to obtain a dl list, disabling writeback\n"); + return -ENOMEM; + } + + dlb = vsp1_dl_list_get_body0(dl_next); + vsp1_dl_body_write(dlb, VI6_WPF_WRBCK_CTRL(index), 0); + vsp1_dl_list_add_chain(dl, dl_next); + + return 0; +} + static void wpf_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, struct vsp1_dl_list *dl, @@ -241,9 +262,11 @@ static void wpf_configure_stream(struct vsp1_entity *entity, struct vsp1_device *vsp1 = wpf->entity.vsp1; const struct v4l2_mbus_framefmt *source_format; const struct v4l2_mbus_framefmt *sink_format; + unsigned int index = wpf->entity.index; unsigned int i; u32 outfmt = 0; u32 srcrpf = 0; + int ret; sink_format = vsp1_entity_get_pad_format(&wpf->entity, wpf->entity.config, @@ -251,8 +274,9 @@ static void wpf_configure_stream(struct vsp1_entity *entity, source_format = vsp1_entity_get_pad_format(&wpf->entity, wpf->entity.config, RWPF_PAD_SOURCE); + /* Format */ - if (!pipe->lif) { + if (!pipe->lif || wpf->writeback) { const struct v4l2_pix_format_mplane *format = &wpf->format; const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; @@ -277,8 +301,7 @@ static void wpf_configure_stream(struct vsp1_entity *entity, vsp1_wpf_write(wpf, dlb, VI6_WPF_DSWAP, fmtinfo->swap); - if (vsp1_feature(vsp1, VSP1_HAS_WPF_HFLIP) && - wpf->entity.index == 0) + if (vsp1_feature(vsp1, VSP1_HAS_WPF_HFLIP) && index == 0) vsp1_wpf_write(wpf, dlb, VI6_WPF_ROT_CTRL, VI6_WPF_ROT_CTRL_LN16 | (256 << VI6_WPF_ROT_CTRL_LMEM_WD_SHIFT)); @@ -289,11 +312,9 @@ static void wpf_configure_stream(struct vsp1_entity *entity, wpf->outfmt = outfmt; - vsp1_dl_body_write(dlb, VI6_DPR_WPF_FPORCH(wpf->entity.index), + vsp1_dl_body_write(dlb, VI6_DPR_WPF_FPORCH(index), VI6_DPR_WPF_FPORCH_FP_WPFN); - vsp1_dl_body_write(dlb, VI6_WPF_WRBCK_CTRL(wpf->entity.index), 0); - /* * Sources. If the pipeline has a single input and BRx is not used, * configure it as the master layer. Otherwise configure all @@ -319,9 +340,26 @@ static void wpf_configure_stream(struct vsp1_entity *entity, vsp1_wpf_write(wpf, dlb, VI6_WPF_SRCRPF, srcrpf); /* Enable interrupts. */ - vsp1_dl_body_write(dlb, VI6_WPF_IRQ_STA(wpf->entity.index), 0); - vsp1_dl_body_write(dlb, VI6_WPF_IRQ_ENB(wpf->entity.index), + vsp1_dl_body_write(dlb, VI6_WPF_IRQ_STA(index), 0); + vsp1_dl_body_write(dlb, VI6_WPF_IRQ_ENB(index), VI6_WFP_IRQ_ENB_DFEE); + + /* + * 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; + } + + vsp1_dl_body_write(dlb, VI6_WPF_WRBCK_CTRL(index), + wpf->writeback ? VI6_WPF_WRBCK_CTRL_WBMD : 0); } static void wpf_configure_frame(struct vsp1_entity *entity, @@ -391,7 +429,11 @@ static void wpf_configure_partition(struct vsp1_entity *entity, (0 << VI6_WPF_SZCLIP_OFST_SHIFT) | (height << VI6_WPF_SZCLIP_SIZE_SHIFT)); - if (pipe->lif) + /* + * For display pipelines without writeback enabled there's no memory + * address to configure, return now. + */ + if (pipe->lif && !wpf->writeback) return; /* @@ -480,6 +522,12 @@ static void wpf_configure_partition(struct vsp1_entity *entity, vsp1_wpf_write(wpf, dlb, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]); vsp1_wpf_write(wpf, dlb, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]); vsp1_wpf_write(wpf, dlb, VI6_WPF_DSTM_ADDR_C1, 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; } static unsigned int wpf_max_width(struct vsp1_entity *entity, -- cgit v1.2.3 From e2ef2a1290842b5a56a13f865310a231c78b5d9a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 21 Feb 2019 03:24:52 +0200 Subject: media: vsp1: drm: Split RPF format setting to separate function The code that initializes the RPF format-related fields for display pipelines will also be useful for the WPF to implement writeback support. Split it from vsp1_du_atomic_update() to a new vsp1_du_pipeline_set_rwpf_format() function. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 55 +++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 20 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index e28a742a7575..d1c88e8aee52 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -566,6 +566,36 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) vsp1_dl_list_commit(dl, dl_flags); } +static int vsp1_du_pipeline_set_rwpf_format(struct vsp1_device *vsp1, + struct vsp1_rwpf *rwpf, + u32 pixelformat, unsigned int pitch) +{ + const struct vsp1_format_info *fmtinfo; + unsigned int chroma_hsub; + + fmtinfo = vsp1_get_format_info(vsp1, pixelformat); + if (!fmtinfo) { + dev_dbg(vsp1->dev, "Unsupported pixel format %08x\n", + pixelformat); + return -EINVAL; + } + + /* + * Only formats with three planes can affect the chroma planes pitch. + * All formats with two planes have a horizontal subsampling value of 2, + * but combine U and V in a single chroma plane, which thus results in + * the luma plane and chroma plane having the same pitch. + */ + chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1; + + rwpf->fmtinfo = fmtinfo; + rwpf->format.num_planes = fmtinfo->planes; + rwpf->format.plane_fmt[0].bytesperline = pitch; + rwpf->format.plane_fmt[1].bytesperline = pitch / chroma_hsub; + + return 0; +} + /* ----------------------------------------------------------------------------- * DU Driver API */ @@ -773,9 +803,8 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, { struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; - const struct vsp1_format_info *fmtinfo; - unsigned int chroma_hsub; struct vsp1_rwpf *rpf; + int ret; if (rpf_index >= vsp1->info->rpf_count) return -EINVAL; @@ -808,25 +837,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, * Store the format, stride, memory buffer address, crop and compose * rectangles and Z-order position and for the input. */ - fmtinfo = vsp1_get_format_info(vsp1, cfg->pixelformat); - if (!fmtinfo) { - dev_dbg(vsp1->dev, "Unsupported pixel format %08x for RPF\n", - cfg->pixelformat); - return -EINVAL; - } - - /* - * Only formats with three planes can affect the chroma planes pitch. - * All formats with two planes have a horizontal subsampling value of 2, - * but combine U and V in a single chroma plane, which thus results in - * the luma plane and chroma plane having the same pitch. - */ - chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1; + ret = vsp1_du_pipeline_set_rwpf_format(vsp1, rpf, cfg->pixelformat, + cfg->pitch); + if (ret < 0) + return ret; - rpf->fmtinfo = fmtinfo; - rpf->format.num_planes = fmtinfo->planes; - rpf->format.plane_fmt[0].bytesperline = cfg->pitch; - rpf->format.plane_fmt[1].bytesperline = cfg->pitch / chroma_hsub; rpf->alpha = cfg->alpha; rpf->mem.addr[0] = cfg->mem[0]; -- cgit v1.2.3 From 09e513e390eab1f2db4d4242ef209cbe0c39c444 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 21 Feb 2019 03:38:06 +0200 Subject: media: vsp1: drm: Extend frame completion API to the DU driver The VSP1 driver will need to pass extra flags to the DU through the frame completion API. Replace the completed bool flag by a bitmask to support this. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.h | 1 + drivers/media/platform/vsp1/vsp1_drm.c | 4 ++-- drivers/media/platform/vsp1/vsp1_drm.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index e0fdb145e6ed..079ba5af0315 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -17,6 +17,7 @@ struct vsp1_dl_body_pool; struct vsp1_dl_list; struct vsp1_dl_manager; +/* Keep these flags in sync with VSP1_DU_STATUS_* in include/media/vsp1.h. */ #define VSP1_DL_FRAME_END_COMPLETED BIT(0) #define VSP1_DL_FRAME_END_INTERNAL BIT(1) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index d1c88e8aee52..bd95683c1cd9 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -34,14 +34,14 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, unsigned int completion) { struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); - bool complete = completion & VSP1_DL_FRAME_END_COMPLETED; if (drm_pipe->du_complete) { struct vsp1_entity *uif = drm_pipe->uif; + unsigned int status = completion & VSP1_DU_STATUS_COMPLETE; u32 crc; crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0; - drm_pipe->du_complete(drm_pipe->du_private, complete, crc); + drm_pipe->du_complete(drm_pipe->du_private, status, crc); } if (completion & VSP1_DL_FRAME_END_INTERNAL) { diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 8dfd274a59e2..e85ad4366fbb 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -42,7 +42,7 @@ struct vsp1_drm_pipeline { struct vsp1_du_crc_config crc; /* Frame synchronisation */ - void (*du_complete)(void *data, bool completed, u32 crc); + void (*du_complete)(void *data, unsigned int status, u32 crc); void *du_private; }; -- cgit v1.2.3 From a63722aeb76c65f39c98c66a1e730a2f3da123ab Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 21 Feb 2019 03:46:42 +0200 Subject: media: vsp1: drm: Implement writeback support Extend the vsp1_du_atomic_flush() API with writeback support by adding format, pitch and memory addresses of the writeback framebuffer. Writeback completion is reported through the existing frame completion callback with a new VSP1_DU_STATUS_WRITEBACK status flag. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 14 ++++++++++++++ drivers/media/platform/vsp1/vsp1_dl.h | 3 ++- drivers/media/platform/vsp1/vsp1_drm.c | 25 ++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index ed7cda4130f2..104b6f514536 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -958,6 +958,9 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl, unsigned int dl_flags) * * The VSP1_DL_FRAME_END_INTERNAL flag indicates that the display list that just * became active had been queued with the internal notification flag. + * + * The VSP1_DL_FRAME_END_WRITEBACK flag indicates that the previously active + * display list had been queued with the writeback flag. */ unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) { @@ -995,6 +998,17 @@ unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) if (status & VI6_STATUS_FLD_STD(dlm->index)) goto done; + /* + * If the active display list has the writeback flag set, the frame + * completion marks the end of the writeback capture. Return the + * VSP1_DL_FRAME_END_WRITEBACK flag and reset the display list's + * writeback flag. + */ + if (dlm->active && (dlm->active->flags & VSP1_DL_FRAME_END_WRITEBACK)) { + flags |= VSP1_DL_FRAME_END_WRITEBACK; + dlm->active->flags &= ~VSP1_DL_FRAME_END_WRITEBACK; + } + /* * The device starts processing the queued display list right after the * frame end interrupt. The display list thus becomes active. diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 079ba5af0315..bebe16483ca5 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -19,7 +19,8 @@ struct vsp1_dl_manager; /* Keep these flags in sync with VSP1_DU_STATUS_* in include/media/vsp1.h. */ #define VSP1_DL_FRAME_END_COMPLETED BIT(0) -#define VSP1_DL_FRAME_END_INTERNAL BIT(1) +#define VSP1_DL_FRAME_END_WRITEBACK BIT(1) +#define VSP1_DL_FRAME_END_INTERNAL BIT(2) /** * struct vsp1_dl_ext_cmd - Extended Display command diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index bd95683c1cd9..a4a45d68a6ef 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -37,7 +37,9 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, if (drm_pipe->du_complete) { struct vsp1_entity *uif = drm_pipe->uif; - unsigned int status = completion & VSP1_DU_STATUS_COMPLETE; + unsigned int status = completion + & (VSP1_DU_STATUS_COMPLETE | + VSP1_DU_STATUS_WRITEBACK); u32 crc; crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0; @@ -541,6 +543,8 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) if (drm_pipe->force_brx_release) dl_flags |= VSP1_DL_FRAME_END_INTERNAL; + if (pipe->output->writeback) + dl_flags |= VSP1_DL_FRAME_END_WRITEBACK; dl = vsp1_dl_list_get(pipe->output->dlm); dlb = vsp1_dl_list_get_body0(dl); @@ -870,12 +874,31 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index, struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; struct vsp1_pipeline *pipe = &drm_pipe->pipe; + int ret; drm_pipe->crc = cfg->crc; mutex_lock(&vsp1->drm->lock); + + if (cfg->writeback.pixelformat) { + const struct vsp1_du_writeback_config *wb_cfg = &cfg->writeback; + + ret = vsp1_du_pipeline_set_rwpf_format(vsp1, pipe->output, + wb_cfg->pixelformat, + wb_cfg->pitch); + if (WARN_ON(ret < 0)) + goto done; + + pipe->output->mem.addr[0] = wb_cfg->mem[0]; + pipe->output->mem.addr[1] = wb_cfg->mem[1]; + pipe->output->mem.addr[2] = wb_cfg->mem[2]; + pipe->output->writeback = true; + } + vsp1_du_pipeline_setup_inputs(vsp1, pipe); vsp1_du_pipeline_configure(pipe); + +done: mutex_unlock(&vsp1->drm->lock); } EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); -- cgit v1.2.3